Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Migrating to the WebApi 2.2 RC and getting Response Status 406 (not acceptable)

I migrated to the WebAPI 2.2 RC (Microsoft.AspNet.WebApi -Version 5.2.0-rc) and I since them I get only 406 (Not Acceptable) as status response on all my queries, for example:

http://localhost:7923/api/Quotes(1)

Status 406

OData Service Configuration

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        config.MapHttpAttributeRoutes();
        config.EnableSystemDiagnosticsTracing();
        config.MapODataServiceRoute("api", "api", CreateEdmModel());
    }

    private static IEdmModel CreateEdmModel()
    {
        var odataModelBuilder = new ODataConventionModelBuilder();

        odataModelBuilder.EntitySet<Tag>("Tags");
        odataModelBuilder.EntitySet<Author>("Authors");
        EntitySetConfiguration<Quote> quoteEntitySetConfiguration = odataModelBuilder.EntitySet<Quote>("Quotes");

        FunctionConfiguration getQuotesRandomFunction = quoteEntitySetConfiguration.EntityType.Collection.Function("Random");
        getQuotesRandomFunction.Parameter<int>("count");
        getQuotesRandomFunction.ReturnsCollectionFromEntitySet<Quote>("Quotes");

        return odataModelBuilder.GetEdmModel();
    }
}

QuotesController

public class QuotesController : ODataController
{
    private WhatAQuoteDb db = new WhatAQuoteDb();

    [ODataRoute("Default.Random(count={count})")]
    [EnableQuery]
    public IHttpActionResult GetQuotesRandom(int count)
    {
        return Ok(db.Quotes.OrderBy(quote => Guid.NewGuid()).Take(count));
    }

    // GET: odata/Quotes
    [EnableQuery]
    public IQueryable<Quote> GetQuotes()
    {
        return db.Quotes;
    }

    // GET: odata/Quotes(5)
    [EnableQuery]
    public SingleResult<Quote> GetQuote([FromODataUri] int key)
    {
        return SingleResult.Create(db.Quotes.Where(quote => quote.Id == key));
    }

    // PUT: odata/Quotes(5)
    public async Task<IHttpActionResult> Put([FromODataUri] int key, Quote quote)
    {
        if (!ModelState.IsValid)
        {
            return BadRequest(ModelState);
        }

        if (key != quote.Id)
        {
            return BadRequest();
        }

        db.Entry(quote).State = EntityState.Modified;

        try
        {
            await db.SaveChangesAsync();
        }
        catch (DbUpdateConcurrencyException)
        {
            if (!QuoteExists(key))
            {
                return NotFound();
            }
            else
            {
                throw;
            }
        }

        return Updated(quote);
    }

    // POST: odata/Quotes
    public async Task<IHttpActionResult> Post(Quote quote)
    {
        if (!ModelState.IsValid)
        {
            return BadRequest(ModelState);
        }

        db.Quotes.Add(quote);
        await db.SaveChangesAsync();

        return Created(quote);
    }

    // PATCH: odata/Quotes(5)
    [AcceptVerbs("PATCH", "MERGE")]
    public async Task<IHttpActionResult> Patch([FromODataUri] int key, Delta<Quote> patch)
    {
        if (!ModelState.IsValid)
        {
            return BadRequest(ModelState);
        }

        Quote quote = await db.Quotes.FindAsync(key);
        if (quote == null)
        {
            return NotFound();
        }

        patch.Patch(quote);

        try
        {
            await db.SaveChangesAsync();
        }
        catch (DbUpdateConcurrencyException)
        {
            if (!QuoteExists(key))
            {
                return NotFound();
            }
            else
            {
                throw;
            }
        }

        return Updated(quote);
    }

    // DELETE: odata/Quotes(5)
    public async Task<IHttpActionResult> Delete([FromODataUri] int key)
    {
        Quote quote = await db.Quotes.FindAsync(key);
        if (quote == null)
        {
            return NotFound();
        }

        db.Quotes.Remove(quote);
        await db.SaveChangesAsync();

        return StatusCode(HttpStatusCode.NoContent);
    }

    // GET: odata/Quotes(5)/Author
    [EnableQuery]
    public SingleResult<Author> GetAuthor([FromODataUri] int key)
    {
        return SingleResult.Create(db.Quotes.Where(m => m.Id == key).Select(m => m.Author));
    }

    // GET: odata/Quotes(5)/Tags
    [EnableQuery]
    public IQueryable<Tag> GetTags([FromODataUri] int key)
    {
        return db.Quotes.Where(m => m.Id == key).SelectMany(m => m.Tags);
    }

    protected override void Dispose(bool disposing)
    {
        if (disposing)
        {
            db.Dispose();
        }
        base.Dispose(disposing);
    }

    private bool QuoteExists(int key)
    {
        return db.Quotes.Count(e => e.Id == key) > 0;
    }
}
like image 468
Anton Kalcik Avatar asked Jun 16 '14 13:06

Anton Kalcik


1 Answers

I checked your solution and found that you used service reference.

However adding service reference doesn't support OData V4 and the version in your generated code is V3.

You can try OData T4 code generator to generate client code.

Check the blog below:

http://blogs.msdn.com/b/odatateam/archive/2014/03/11/how-to-use-odata-client-code-generator-to-generate-client-side-proxy-class.aspx


Update:

I checked your solution again and found the problem:

The ODataController you used is V3!

If you want the V4 version, you need to change the using namespace in your controller cs file

From

using System.Web.Http.OData;

To

using System.Web.OData;

What is more, there is other problem that the following template is invalid when I start up the project.

[ODataRoute("Default.Random(count={count})")]

I guest that the random function you defined is a function import and you should define like this:

FunctionConfiguration getQuotesRandomFunction = odataModelBuilder.Function("Random");

And the function import should not add namespace and the template should be:

[ODataRoute("Random(count={count})")]

Let me know if you have other problems.

like image 77
Feng Zhao Avatar answered Sep 30 '22 18:09

Feng Zhao