Jeroen E
Jeroen E

Reputation: 57

WebApi OData Delete routing convention

I have a MVVM project. For the model I use a EF6.0.0 code first and WebApi.

In general everything works fine but for one thing.

When I do a delete the following URL is composed

http://localhost:50346/Recruiters/Addresses(guid'5d778c9d-56b2-449b-b655-22489e01636d')/CIP.Models.Domain.Addresses

and this results in a 404 error.

So I've created an routing convention like this:

using Microsoft.Data.Edm;
using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Linq;
using System.Net.Http;
using System.Web;
using System.Web.Http.Controllers;
using System.Web.Http.OData.Routing;
using System.Web.Http.OData.Routing.Conventions;

namespace CIP
{
    public class AddressesRoutingConvention : EntitySetRoutingConvention
{
    public override string SelectAction(ODataPath odataPath, HttpControllerContext controllerContext, ILookup<string, HttpActionDescriptor> actionMap)
    {
        if (odataPath.PathTemplate == "~/entityset/key/cast")
        {
            HttpMethod httpMethod = controllerContext.Request.Method;
            string httpMethodName;

            switch (httpMethod.ToString().ToUpperInvariant())
            { 
                case "DELETE":
                    httpMethodName = "Delete";
                    break;
                default:
                    return null;
            }

            Contract.Assert(httpMethodName != null);

            IEdmEntityType entityType = odataPath.EdmType as IEdmEntityType;

            string actionName = httpMethodName + entityType.Name;                    

            if (actionName != null)
            {
                KeyValuePathSegment keyValueSegment = odataPath.Segments[1] as KeyValuePathSegment;
                controllerContext.RouteData.Values[ODataRouteConstants.Key] = keyValueSegment.Value;
                return actionName;
            }
        }
        // Not a match
        return null;
    }
}
}

and added this route

var conventions = ODataRoutingConventions.CreateDefault();
conventions.Insert(0, new AddressesRoutingConvention());

config.Routes.MapODataRoute("Addresses", "Addresses", addressesBuilder.GetEdmModel(), new DefaultODataPathHandler(), conventions);`

And in the controller

public async Task<IHttpActionResult> DeleteAddresses([FromODataUri] Guid key)
{
    Addresses addresses = await db.Addresses.FindAsync(key);
    if (addresses == null)
    {
        return NotFound();
    }

    db.Addresses.Remove(addresses);
    await db.SaveChangesAsync();

    return StatusCode(HttpStatusCode.NoContent);
}

But still I get the 404 error.

I tried testing it from SOAPUI with the same result.

Am I missing something?

Kind regards

Jeroen

Upvotes: 0

Views: 1508

Answers (2)

Jeroen E
Jeroen E

Reputation: 57

Few small errors aside the code is ok.

It turns out the problem was in my web.config. After adding below configuration to it, everything works, even breakpoints:

<system.webServer>
    <handlers>
      <clear/>
      <add name="ExtensionlessUrlHandler-Integrated-4.0" path="/*" 
          verb="*" type="System.Web.Handlers.TransferRequestHandler" 
      preCondition="integratedMode,runtimeVersionv4.0" />
    </handlers>
</system.webServer>  

Jeroen

Upvotes: 0

Sam Xu
Sam Xu

Reputation: 3380

Jeroen

I think What you have done can work.

However, your below request Uri is not right based on your OData route setting:

http://localhost:50346/Recruiters/Addresses(guid'5d778c9d-56b2-449b-b655-22489e01636d')/CIP.Models.Domain.Addresses 

Because your OData route setting is:

config.Routes.MapODataRoute("Addresses", "Addresses", addressesBuilder.GetEdmModel(), ...

So, your request Uri should be:

http://localhost:50346/Addresses/Addresses(guid'5d778c9d-56b2-449b-b655-22489e01636d')/CIP.Models.Domain.Addresses 

Why do you write "Recruiters" ?

Here's my debug information using all your sample codes: enter image description here

Besides, Why do you issue a **Delete** request on a cast Uri? It seems the last type case segment (that is: CIP.Models.Domain.Addresses) is not necessary?

You can refer to Delete an Entity section from OData Spec. If you find any issue for Web API OData, you can directly file an issue on WebApi OData On Github. Thanks.

Thanks.

Upvotes: 0

Related Questions