web 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
Заменете първия си маршрут с този routes.MapRoute( име: DevicesAPIRoute, url: DevicesAPI/GetLatestDevice/{latestUpdate}, по подразбиране: нов { контролер = DevicesAPI, действие = 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
Само за заобиколно решение можете ли да коментирате първия маршрут (означава твърдо кодиран). запазете само един маршрут там и променете името на вашия параметър за действие като id. и опитайте това, ако работи за вас. - 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//DevicesAPI?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