веб-API 2 возвращает ошибку

Я создал новое действие веб-API и добавил для него новую маршрутизацию. Я не уверен, что сделал это правильно, скорее всего, нет, поэтому я получаю эту ошибку.

Итак, я добавил свой метод/действие, подобное этому

    public IQueryable<Devices> GetLatestDevice(DateTime? latestUpdate)
    {
        return db.devices.Where(dev => dev.UpdatedDate > latestUpdate); ;
    }

а это моя таблица маршрутизации

        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
        //routes.IgnoreRoute("");
        routes.MapRoute(
            name: "Device",
            url: "{controller}/{action}/{lastUpdate}",
            defaults: new { controller = "Home", action = "Index", lastUpdate = UrlParameter.Optional }
        );

        routes.MapRoute(
            name: "Default",
            url: "{controller}/{action}/{id}",
            defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
        );

и вот как я пытаюсь получить данные:

http://localhost:53658/api/DevicesAPI/21-01-2001

    <Error><Message>An error has occurred.</Message><ExceptionMessage>Multiple actions were found that match the request: 
GetLatestDevice on type WhitespiderMonitor.Controllers.DevicesAPIController
GetDevices on type WhitespiderMonitor.Controllers.DevicesAPIController</ExceptionMessage><ExceptionType>System.InvalidOperationException</ExceptionType><StackTrace>   at System.Web.Http.Controllers.ApiControllerActionSelector.ActionSelectorCacheItem.SelectAction(HttpControllerContext controllerContext)
   at System.Web.Http.Controllers.ApiControllerActionSelector.SelectAction(HttpControllerContext controllerContext)
   at System.Web.Http.ApiController.ExecuteAsync(HttpControllerContext controllerContext, CancellationToken cancellationToken)
   at System.Web.Http.Dispatcher.HttpControllerDispatcher.<SendAsync>d__1.MoveNext()</StackTrace></Error>

Я предполагаю, что, поскольку маршруты почти одинаковы, он не может различить их, поэтому мои вопросы действительно таковы, прав ли я в том, что они одинаковы, и как мне получить его, чтобы он выбрал дату. При необходимости можно предоставить дополнительную информацию, спасибо!

Я не обновлял таблицу маршрутов до

routes.MapRoute(
            name: "Device",
            url: "DevicesAPI/GetLatestDevice/{lastUpdate}",
            defaults: new { lastUpdate = UrlParameter.Optional }
        );

и теперь получить эту ошибку:

<Error><Message>The request is invalid.</Message><MessageDetail>The parameters dictionary contains a null entry for parameter 'id' of non-nullable type 'System.Int64' for method 'System.Web.Http.IHttpActionResult GetDevices(Int64)' in 'WhitespiderMonitor.Controllers.DevicesAPIController'. An optional parameter must be a reference type, a nullable type, or be declared as an optional parameter.</MessageDetail></Error>

person Johnathon64    schedule 13.07.2015    source источник
comment
Оба ваших маршрута являются общими и соответствуют одному и тому же запросу. Просто жестко закодируйте контроллер и имя действия. например, замените этот URL-адрес: {controller}/{action}/{lastUpdate} на URL-адрес: Device/GetLatestDevice/{lastUpdate}   -  person Anupam Sharma    schedule 13.07.2015
comment
Итак, я должен удалить маршрут, который я только что создал, и просто использовать жестко заданный URL-адрес?   -  person Johnathon64    schedule 13.07.2015
comment
нет заменить первое значение URL-адреса маршрута на это. Должен быть один маршрут с динамическим контроллером и именем действия, чтобы другие функции не влияли.   -  person Anupam Sharma    schedule 13.07.2015
comment
@AnupamSharma, поэтому я пробовал это localhost:53658/api/DevicesAPI/GetLatestDevices/21 -01-2001 и получил ошибку 404, а также попробовал ваше предложение localhost :53658/DevicesAPI/GetLatestDevices/21-01-2001 и получил еще одну ошибку о том, что ресурс не найден. Я также пытался сделать это следующим образом: localhost:53658/api// DevicesAPI/, но сказал то же самое, что и выше, что было несколько одинаковых действий   -  person Johnathon64    schedule 13.07.2015
comment
Сохраните оба маршрута, один с жестко заданным значением, а другой с динамическим значением, как сейчас. Или вы можете сделать еще одно, например, сделать имя параметра таким же и оставить только один общий корень.   -  person Anupam Sharma    schedule 13.07.2015
comment
как называется твой контроллер??   -  person Anupam Sharma    schedule 13.07.2015
comment
Имя контроллера — DevicesAPI.   -  person Johnathon64    schedule 13.07.2015
comment
Замените свой первый маршрут на этот route.MapRoute(имя: DevicesAPIRoute, url: DevicesAPI/GetLatestDevice/{latestUpdate}, значения по умолчанию: new {controller = DevicesAPI, action = GetLatestDevice, lastUpdate = UrlParameter.Optional});   -  person Anupam Sharma    schedule 13.07.2015
comment
Я сделал это, но получил указанную выше ошибку при попытке использовать URL-адрес localhost:53658/ api/DevicesAPI/21-01-2001 Я исправил пост выше   -  person Johnathon64    schedule 13.07.2015
comment
Pz попробуйте ответ, который я разместил.   -  person Anupam Sharma    schedule 13.07.2015
comment
Давайте продолжим обсуждение в чате.   -  person Anupam Sharma    schedule 13.07.2015
comment
прочитайте stackoverflow.com/questions/31287928/   -  person Amit Kumar Ghosh    schedule 14.07.2015


Ответы (4)


пожалуйста, замените метод действия приведенным ниже кодом.

   public IQueryable<Devices> GetLatestDevice(DateTime latestUpdate)
    {
        return db.devices.Where(dev => dev.UpdatedDate > latestUpdate); 
    }

И добавьте приведенный ниже код маршрутизации в WebAPIConfig.cs перед существующим кодом маршрутизации по умолчанию.

     Routes.MapHttpRoute(
         name: "CustomApi",
         routeTemplate:"api/{controller}/{action}/{latestUpdate:DateTime?}",
         defaults: new { controller:"DevicesAPI",latestUpdate = RouteParameter.Optional }
            );
person chiru    schedule 14.07.2015

У вас есть два общих маршрута. Вы можете изменить его на что-то вроде:

routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
    //routes.IgnoreRoute("");
    routes.MapRoute(
        name: "Device",
        url: "device/{action}/{lastUpdate}",
        defaults: new { controller = "Device", action = "Index", lastUpdate = UrlParameter.Optional }
    );

    routes.MapRoute(
        name: "Default",
        url: "{controller}/{action}/{id}",
        defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
    );

Таким образом, конкретный будет срабатывать при использовании контроллера Device.

person kamil-mrzyglod    schedule 13.07.2015

Ваш маршрут должен быть таким:

routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
        //routes.IgnoreRoute("");
        routes.MapRoute( name: "DevicesAPIRoute", 
                          url:"DevicesAPI/GetLatestDevice/{latestUpdate}", 
                          defaults: new { controller = "DevicesAPI", action = "GetLatestDevice", lastUpdate = UrlParameter.Optional } ); 

        routes.MapRoute(
            name: "Default",
            url: "{controller}/{action}/{id}",
            defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
        );
person Anupam Sharma    schedule 13.07.2015
comment
URL, который вы пытаетесь? - person Anupam Sharma; 13.07.2015
comment
Просто для обходного пути вы можете закомментировать первый маршрут (имеется в виду жестко закодированный). оставьте там только один маршрут и измените имя параметра действия на идентификатор. и попробуйте это, если это работает для вас. - person Anupam Sharma; 13.07.2015
comment
У меня 404 ресурс не найден, я пробовал другие действия и они работают. - person Johnathon64; 13.07.2015
comment
удалите API из URL-адреса или добавьте его также в маршрут - person Anupam Sharma; 13.07.2015
comment
Пробовал так и тоже не получилось. Кажется, он не хочет использовать новый метод, который я добавил в - person Johnathon64; 13.07.2015
comment
Итак, очевидно, если я пишу свой маршрут таким образом, он работает localhost:53658/ API//API устройств?lastUpdate=21-02-2012 - person Johnathon64; 13.07.2015

Другим решением было бы добавить параметр action в ваш код маршрутизации, например:

Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{action}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );

Вам нужно будет передать имя action в своем URL-адресе следующим образом:

http://localhost:53658/api/DevicesAPI/{your action name}/21-01-2001

введите здесь описание изображениявведите здесь описание изображения введите здесь описание изображениявведите здесь описание изображения

person Amit Kumar Ghosh    schedule 13.07.2015
comment
@ Johnathon64, можешь попробовать? - person Amit Kumar Ghosh; 13.07.2015