Thursday, August 13, 2015

Vino VNC asks for keyring password

When you try to connect with VNC to your Ubuntu desktop which has Vino configured and running, it may trigger a gnome keyring password prompt on the local display, and the login process hangs on the remote end. There are many solutions around, and most of them leave the system somewhat dirty. Here's a procedure I've gathered which fixes the problem, even remotely, and leave the system clean.

First of all, we need to shut down the gnome keyring daemon. But I've found that all application trying to gain access to the keyring will cause it to launch. So I found the only way to stop it without removing it is to rename it. Temporarily, don't worry:

sudo mv /usr/bin/gnome-keyring-daemon /usr/bin/gnome-keyring-daemon.bak
sudo reboot

Then you should be able to connect to the remote machine with VNC. But let's not stop here and do things proper. First, reenable gnome keyring daemon and launch it so it is available to the next step:

sudo mv /usr/bin/gnome-keyring-daemon.bak /usr/bin/gnome-keyring-daemon
gnome-keyring-daemon

Make sure seahorse is installed and launch it from the VNC session. It's in System / Preferences / Passwords and Keys.

Now there's this "Login" folder. Unlock it by right clicking and choosing Unlock.

In the login folder, you will find an item named Vino. Right click on it and delete it.

And that's it. You can make sure everything is fixed by rebooting and trying to connect with VNC again.

I believe you have to leave the VNC password blank. Otherwise it'll create this item in the keyring. Feel free to confirm this in the comments. I've pulled too much hair out for this already ;)

Thursday, February 5, 2015

WebAPI OData v4: Cannot serialize a null 'entry'

In that kind of function:

public IHttpActionResult MyFunction([FromODataUri]int myParameter)
{
 return Ok(GetFoo(myParameter));
}

This may lead to the error 500 described in the title if the returned value is null. Based on this thread, One way would be to return an empty response when the return value is null:

public IHttpActionResult MyFunction([FromODataUri]int myParameter)
{
 var retval = GetFoo(myParameter);
 if (retval != null)
  return Ok(retval);
 else
  return Ok();
}

The result is a 202 OK empty response, but this doesn't seem to please some OData frameworks as I sometimes get a "Unexpected server response" message on the client side.

Now, based on this other thread, it seems the clean way to do this is to return a 404 error when the return value is null and act accordingly on the client side:

public IHttpActionResult MyFunction([FromODataUri]int myParameter)
{
 var retval = GetFoo(myParameter);
 if (retval != null)
  return Ok(retval);
 else
  return NotFound();
}


Wednesday, January 14, 2015

WebAPI OData: Only entity types support $select and $expand

I used to get this because I was trying to return a complex type which was not an entity type and use "expand" on it so to get a child property:

builder.EntitySet<MyComplexType>("MyComplexTypes").EntityType.Collection.Action("MyAction").Returns<MyComplexType>()
[HttpPost, EnableQuery(AllowedQueryOptions = AllowedQueryOptions.Expand)]
public IHttpActionResult MyAction(ODataActionParameters parameters)
{
 return Ok(new MyComplexType());
}

http://host/api/Entities/Default.MyAction?$expand=ChildProperty

Accessing this URL triggers:

"Only entity types support $select and $expand"

Instead of converting the type, which would have made non sens in my situation, here's what I did:

builder.EntitySet<MyComplexType>("MyComplexTypes").EntityType.Collection.Action("MyAction").Returns<string>()
[HttpPost]
public IHttpActionResult MyAction(ODataActionParameters parameters)
{
 return Json(new MyComplexType());
}

http://host/api/Entities/Default.MyAction

This returns a new MyComplexType object with all its children properties serialized.

Saturday, December 13, 2014

Play C64 SID files under Linux

VLC didn't work, neither did totem, and couldn't get sidplay to work.

Install audacity
then install the "exotic" plugins package, namely audacious-plugins-exotic

There you go. You can load and play your sid files from within audacity.


Thursday, December 4, 2014

ASP.Net OData V4 with inherited key: A primitive value was specified; however, a value of the non-primitive type '' was expected

At the time of writing this, there is absolutely no help on the net on this error I keep on getting. By trial and error, I've been able not to explain the message, but at least find the cause.

In my case, I have two classes:

class BaseClass
{
  public int ID {get; set;}
}
class DerivedClass : BaseClass {  public string A { get; set; }
}

And in the modelBuilder configuration (which may not be necessary here but in my case, the builder would treat some other property as the primary key instead of this one and caused other cryptic errors):

builder.EntitySet<DerivedClass>("DerivedClasses").EntityType.HasKey(c => c.ID);

Now in my DerivesClassesController ODataController, if I try to access the derived class like so:

http://someaddress/api/DerivedClasses

I get this OData V4 formatted error (in french) :
{ "error":{ "code":"","message":"An error has occurred.","innererror":{ "message":"The 'ObjectContent`1' type failed to serialize the response body for content type 'application/json; odata.metadata=minimal'.","type":"System.InvalidOperationException","stacktrace":"","internalexception":{ "message":"Une valeur primitive a \u00e9t\u00e9 sp\u00e9cifi\u00e9e alors qu'une valeur de type non primitif '' \u00e9tait attendue.","type":"Microsoft.OData.Core.ODataException","stacktrace":" \u00e0 Microsoft.OData.Core.ValidationUtils.ValidateIsExpectedPrimitiveType(Object value, IEdmPrimitiveTypeReference valuePrimitiveTypeReference, IEdmTypeReference expectedTypeReference, Boolean bypassValidation)\r\n \u00e0 .............................
(Here I used to suggest defining a "new int ID" in the DerivedClass which worked but was kind of dirty and defeated the whole base class purpose. Here's a better way:)

The trick is to map the base class' ID property:

builder.EntityType<BaseClass>().HasKey(c => c.ID);

And do not remap the key on each derived class or you'll end up with a cryptic "The sequence contains more than one element" error.

The problem with this, however, is that the builder will try to map every entity that is inherited from the base class which you might or might not want. As of this writing, there is no way of preventing this automatic discovery.

So another trick is to explicitly ignore all derived types and only after that, remap wanted entities. Doing this by hand would be problematic wouldn't it. So here's a nice reflective loop that'll do the ignore part in a couple of lines. Place this just after the base class key definition so you end up with:

builder.EntitySet<DerivedClass>("DerivedClasses").EntityType.HasKey(c => c.ID);

var types = AppDomain.CurrentDomain.GetAssemblies()
 .SelectMany(a => a.GetTypes())
 .Where(t => t.IsSubclassOf(typeof(AbstractModel)));

foreach (var type in types)
 builder.Ignore(types.ToArray());

Then proceed on the derived types mappings as usual.

Wednesday, December 3, 2014

ASP.Net: OData V4 Controller giving 406

What an obscure one...

If you have a seemingly complete controller and opening this url:

http://yoursite/api/Products

returns actual OData v4 results BUT this:

http://yoursite/api/Products(1)

returns a 404 error with:

No type was found that matches the controller named 'Products(1)'

then make sure your "using"s are adequate in your controller:

using System.Web.OData; <-- this should be used

vs

using System.Web.Http.OData;

By default, the WebAPI 2 ODataController template generates a class with the latter, and it gave me trouble.

Friday, November 28, 2014

ASP.Net: Web API 2 + Help Pages + OData

Doing each of them separately is fairly easy and there's lots of tutorials on how to do it. But as for mixing them together, I've not seen much. Some blogs claim it's not possible and buggy and mostly lead to 404 and 406 errors. Well, out of luck, I made it work. The secret is in the ROUTING!

I don't understand all the concepts behind this and I believe most of us don't, and don't care to. Still, feel free to explain the unexplained in the comments.

So, I started with a ASP.Net Application project. I Selected Web API for the template so I could have the help pages ready. Then I added the needed stuff for OData V4 following this really nice tutorial. Last, I had to configure the ROUTES, and that is where all hell resides (well, that's what all the blog posts and obscure SO questions lead me to think). THe following has been taken from my SO answer.

The order in which the routes are configured has an impact. In my case, I also have some standard MVC controllers and help pages.

Global.asax:
protected void Application_Start()
{
 AreaRegistration.RegisterAllAreas();
 GlobalConfiguration.Configure(config =>
 {
  ODataConfig.Register(config); //this has to be before WebApi
  WebApiConfig.Register(config);
 });
 FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
 RouteConfig.RegisterRoutes(RouteTable.Routes);
}

The filter and routeTable parts weren't there when I started my project and are needed.

ODataConfig.cs:
public static void Register(HttpConfiguration config)
{
  config.MapHttpAttributeRoutes(); //This has to be called before the following OData mapping, so also before WebApi mapping
    
  ODataConventionModelBuilder builder = new ODataConventionModelBuilder();
    
  builder.EntitySet("Sites");
  //Moar!
    
  config.MapODataServiceRoute("ODataRoute", "api", builder.GetEdmModel());
}

WebApiConfig.cs:
public static void Register(HttpConfiguration config)
{
  config.Routes.MapHttpRoute( //MapHTTPRoute for controllers inheriting ApiController
     name: "DefaultApi",
     routeTemplate: "api/{controller}/{id}",
     defaults: new { id = RouteParameter.Optional }
  );
}

RouteConfig.cs:
public static void RegisterRoutes(RouteCollection routes)
{
  routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
    
  routes.MapRoute( //MapRoute for controllers inheriting from standard Controller
    name: "Default",
    url: "{controller}/{action}/{id}",
    defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
  );
}

This has to be in that EXACT ORDER. I tried moving the calls around and ended up with either MVC, Api or Odata broken with 404 or 406 errors.

So I can call:

localhost:xxx/ -> leads to help pages (home controller, index page)

localhost:xxx/api/ -> leads to the OData $metadata

localhost:xxx/api/Sites -> leads to the Get method of my SitesController inheriting from ODataController

localhost:xxx/api/Test -> leads to the Get method of my TestController inheriting from ApiController.