1
Vote

'/', '\' and ' ' is not handled correctly in string primary key in edit link

description

'/', '\' can't route to the correct action
' ' will be null value when binding to the id parameter.

Repro code:
    public static void RegisterODataRoutes(this HttpConfiguration configuration)
    {
        // Metadata routes to support $metadata and code generation in the WCF Data Service client.
        configuration.Routes.MapHttpRoute(ODataRouteNames.Metadata, "$metadata", new { Controller = "ODataMetadata", Action = "GetMetadata" });
        configuration.Routes.MapHttpRoute(ODataRouteNames.ServiceDocument, string.Empty, new { Controller = "ODataMetadata", Action = "GetServiceDocument" });

        // Relationship routes (notice the parameters is {type}Id not id, this avoids colliding with GetById(id)).
        configuration.Routes.MapHttpRoute(ODataRouteNames.PropertyNavigation, "{controller}({parentId})/{navigationProperty}");

        // Route for manipulating links.
        //configuration.Routes.MapHttpRoute(ODataRouteNames.Link, "{controller}({id})/$links/Products");
        configuration.Routes.MapHttpRoute(ODataRouteNames.Link, "{controller}({id})/$links/{navigationProperty}");

        // Routes for urls both producing and handling urls like ~/Product(1), ~/Products() and ~/Products
        configuration.Routes.MapHttpRoute("GetByStringId", "{controller}('{id}')");
        configuration.Routes.MapHttpRoute(ODataRouteNames.GetById, "{controller}({id})");
        configuration.Routes.MapHttpRoute(ODataRouteNames.DefaultWithParentheses, "{controller}()");
        configuration.Routes.MapHttpRoute(ODataRouteNames.Default, "{controller}");
    }

[EntitySetAttribute("todo")]
[DataServiceKeyAttribute("Name")]
public class Todo
{
    [Key]
    public string Name { get; set; }
}

public class TodoController : ApiController
{
    static TodoController()
    {
        var todoes = new List<Todo>();
        foreach (var c in "/ \\")
        {
            todoes.Add(new Todo()
            {
                Name = c.ToString()
            });
        }
        Todoes = todoes;
    }

    public static IEnumerable<Todo> Todoes { get; set; }

    public IEnumerable<Todo> Get()
    {
        return Todoes;
    }

    public Todo GetById(string id)
    {
        return Todoes.FirstOrDefault(t => t.Name == id);
    }

    [AcceptVerbs("Merge")]
    public Todo Put(string id, Todo todo)
    {
        todo = Todoes.FirstOrDefault(t => t.Name == id);
        return todo;
    }
}
Client code:
    [Fact]
    public void TestSpecialCharacters()
    {
        DataServiceContext ctx = new DataServiceContext(new Uri(this.BaseAddress));
        var todoes = ctx.CreateQuery<Todo>("todo").ToList();

        foreach (var todo in todoes)
        {
            Uri selfLink;
            Assert.True(ctx.TryGetUri(todo, out selfLink));
            Console.WriteLine(selfLink);

            ctx.UpdateObject(todo);

            var response = ctx.SaveChanges().Single();

            Assert.Equal(200, response.StatusCode);
        }
    }

comments

raghuramn wrote Nov 7, 2012 at 9:58 PM

won't fix. As discussed, this is a selfhost issue. Selfhost has routing issues with urls containing encoded / in the path.

** Closed by raghuramn 11/07/2012 2:58PM

hongyes wrote May 10 at 12:55 AM

The same issue now happens for ? and #. # is failed in webhost, too. (? is denied in webhost as dangerous character).

hongyes wrote May 10 at 12:56 AM

Reopen the issue with comment above.