Действие OData V3 в веб-API ASP.NET не срабатывает

Я использую конечные точки OData V3, используя asp.net с webapi 2.2. Я успешно реализовал с ним операцию CRUD. Теперь я хотел бы добавить некоторые пользовательские действия вместе с операциями CRUD. Я следил за статьей ( http://www.asp.net/web-api/overview/odata-support-in-aspnet-web-api/odata-v3/odata-actions), чтобы создать действие с OData. V3 с веб-API.

Когда я печатаю

URI:

http://localhost:55351/odata/Courses(1101)/AlterCredits

выдает следующую ошибку:

<m:error><m:code/><m:message xml:lang="en-US">No HTTP resource was found that matches the request URI 'http://localhost:55351/odata/Courses(1101)/AlterCredits'.</m:message><m:innererror><m:message>No routing convention was found to select an action for the OData path with template '~/entityset/key/unresolved'.</m:message><m:type/><m:stacktrace/></m:innererror></m:error>

Я также попытался добавить настраиваемый маршрут для действий без привязки. (https://aspnet.codeplex.com/SourceControl/latest#Samples/WebApi/OData/v3/ODataActionsSample/ODataActionsSample/App_Start/WebApiConfig.cs ) Не уверен, что мне нужно это использовать.

Вот мой код:

WebApiConfig.cs: ---

namespace ODataV3Service
{
public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        IList<IODataRoutingConvention> conventions = ODataRoutingConventions.CreateDefault(); //Do I need this?
        //conventions.Insert(0, new NonBindableActionRoutingConvention("NonBindableActions"));

        // Web API routes                        
        config.Routes.MapODataRoute("ODataRoute","odata", GetModel(), new DefaultODataPathHandler(), conventions);
    }

    private static IEdmModel GetModel()
    {
        ODataModelBuilder modelBuilder = new ODataConventionModelBuilder();
        modelBuilder.ContainerName = "CollegeContainer";
        modelBuilder.EntitySet<Course>("Courses");
        modelBuilder.EntitySet<Department>("Departments");

        //URI: ~/odata/Course/AlterCredits
        ActionConfiguration atlerCredits = modelBuilder.Entity<Course>().Collection.Action("AlterCredits");
        atlerCredits.Parameter<int>("Credit");
        atlerCredits.Returns<int>();

        return modelBuilder.GetEdmModel();
    }
  }
}

КурсыКонтроллер.cs:----

[HttpPost]        
    //[ODataRoute("AlterCredits(key={key},credit={credit})")]
    public async Task<IHttpActionResult> AlterCredits([FromODataUri] int key, ODataActionParameters parameters)
    {            
        if (!ModelState.IsValid)
            return BadRequest();

        Course course = await db.Courses.FindAsync(key);
        if (course == null)
        {
            return NotFound();
        }

        int credits = course.Credits + 3;

        return Ok(credits);
    }

Global.asax:----

namespace ODataV3Service
{
 public class WebApiApplication : System.Web.HttpApplication
 {
    protected void Application_Start()
    {
        GlobalConfiguration.Configure(WebApiConfig.Register);
    }
 }
}

Я провел исследование в Интернете и нашел эту ссылку. Веб-API и OData-передача нескольких параметров Но это для OData V4. Я использую OData V3 и Action.

Спасибо,


person user659469    schedule 15.10.2014    source источник


Ответы (1)


Во-первых, ваше действие AlterCredits определяется как:

ActionConfiguration atlerCredits = modelBuilder.Entity<Course>().Collection.Action("AlterCredits");

Это означает, что AlterCredits привязывается к коллекции Course.

Во-вторых, ваш метод AlterCredits в вашем контроллере определяется как:

public async Task<IHttpActionResult> AlterCredits([FromODataUri] int key, ODataActionParameters parameters)
{
...
}

Это означает, что AlterCredits прослушайте вызов сущности Course.

Таким образом, вы получили сообщение об ошибке Ресурс HTTP не найден.


На основе вашего примера кода я создаю пример метода для справки:

[HttpPost]
public async Task<IHttpActionResult> AlterCredits(ODataActionParameters parameters)
{
    if (!ModelState.IsValid)
        return BadRequest();

    object value;
    if (parameters.TryGetValue("Credit", out value))
    {
        int credits = (int)value;
        credits = credits + 3;
        return Ok(credits);
    }

    return NotFound();
}

Затем, если вы отправляете запрос:

POST ~/odata/Courses/AlterCredits
Content-Type: application/json;odata=verbose
Content: {"Credit":9}

Вы можете получить такой ответ:

{
  "d":{
    "AlterCredits":12
  }
}

На ваши вопросы:

  1. Соглашения IList = ODataRoutingConventions.CreateDefault(); //Мне это нужно?

    Ответ: нет, не нужно. Просто используя значение по умолчанию как:

    config.Routes.MapODataServiceRoute("ODataRoute", "odata", GetModel());

  2. //[ODataRoute("AlterCredits(key={key},credit={credit})")]

    Ответ: нет, вам не нужен атрибут ODataRouteAttribute для действия привязки.

Спасибо.

person Sam Xu    schedule 14.11.2014