ASP.NET वेब एपीआई में कस्टम विधि के नाम


110

मैं WCF वेब एपीआई से नए ASP.NET MVC 4 वेब एपीआई में परिवर्तित कर रहा हूं। मेरे पास एक UsersController है, और मैं एक विधि का नाम प्रमाणीकरण करना चाहता हूं। मैं GetAll, GetOne, Post, और Delete कैसे करें का उदाहरण देखता हूं, हालांकि क्या होगा अगर मैं इन सेवाओं में अतिरिक्त तरीके जोड़ना चाहता हूं? उदाहरण के लिए, मेरे उपयोगकर्ता सेवा में एक विधि होनी चाहिए जिसे प्रमाणीकरण कहा जाता है जहां वे एक उपयोगकर्ता नाम और पासवर्ड में पास होते हैं, हालांकि यह काम नहीं करता है।

public class UsersController : BaseApiController
{
    public string GetAll()
    {
        return "getall!";
    }

    public string Get(int id)
    {
        return "get 1! " + id;
    }

    public User GetAuthenticate(string userName, string password, string applicationName)
    {
        LogWriter.Write(String.Format("Received authenticate request for username {0} and password {1} and application {2}",
            userName, password, applicationName));

        //check if valid leapfrog login.
        var decodedUsername = userName.Replace("%40", "@");
        var encodedPassword = password.Length > 0 ? Utility.HashString(password) : String.Empty;
        var leapFrogUsers = LeapFrogUserData.FindAll(decodedUsername, encodedPassword);

        if (leapFrogUsers.Count > 0)
        {
            return new User
            {
                Id = (uint)leapFrogUsers[0].Id,
                Guid = leapFrogUsers[0].Guid
            };
        }
        else
            throw new HttpResponseException("Invalid login credentials");
    }
}

मैं myapi / api / users / को ब्राउज़ कर सकता हूं और यह GetAll को कॉल करेगा और मैं myapi / api / users / 1 को ब्राउज़ कर सकता हूं और यह Get को कॉल करेगा, हालांकि अगर मैं myapi / api / users / प्रमाणिकता कहता हूं? उपयोगकर्ता नाम = {0} & पासवर्ड = {1} तब इसे गेट (नहीं प्रमाणीकरण) और त्रुटि कहेंगे:

पैरामीटर डिक्शनरी में नॉन-न्युलेबल टाइप 'System.Int32' के पैरामीटर 'id' के लिए 'नोवल एंट्री.सर्विस.CF.NavtrakAPI .Controllers.UsersController' का एक नॉर्थ एंट्री होता है। एक वैकल्पिक पैरामीटर एक संदर्भ प्रकार, एक अशक्त प्रकार होना चाहिए, या एक वैकल्पिक पैरामीटर के रूप में घोषित किया जाना चाहिए।

मैं कस्टम विधि नाम जैसे प्रमाणीकरण कैसे कह सकता हूं?


कृपया इस लिंक को देखें: 5th उत्तर stackoverflow.com/questions/12775590/…
Vishwa G

जवाबों:


136

डिफ़ॉल्ट रूप से मार्ग विन्यास RESTFul सम्मेलनों का अर्थ है कि यह केवल गेट, पोस्ट, पुट और डिलीट एक्शन नामों को स्वीकार करेगा (वैश्विक रूप से मार्ग को देखें) = डिफ़ॉल्ट रूप से यह आपको किसी भी एक्शन नाम को निर्दिष्ट करने की अनुमति नहीं देता है => यह HTTP वर्ब को भेजने के लिए उपयोग करता है)। इसलिए जब आप एक GET अनुरोध भेजते हैं तो आप /api/users/authenticateमूल रूप से Get(int id)कार्रवाई को कॉल कर रहे हैं और id=authenticateजो स्पष्ट रूप से क्रैश हो रहा है क्योंकि आपका गेट एक्शन पूर्णांक की अपेक्षा करता है।

यदि आप मानक मार्ग की तुलना में भिन्न क्रिया नाम रखना चाहते हैं, तो आप अपने रूट की परिभाषा को संशोधित कर सकते हैं global.asax:

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

अब आप /api/values/getauthenticateउपयोगकर्ता को प्रमाणित करने के लिए नेविगेट कर सकते हैं ।


20
क्या अभी भी अन्य कार्यों की अनुमति देते हुए, इसे प्राप्त करने के लिए (आईडी), गेट () रखो, हटाओ, पोस्ट करें का उपयोग करने का एक तरीका है?
शॉन मैक्लेन

@ShawnMclean मुझे लगता है कि बिना आप एक और मार्ग निर्दिष्ट कर सकते हैं {action}कि पर एक बाधा है {id}ताकि कुछ भी अन्य की तुलना में intया Guid(या जो भी) से मेल नहीं होता। फिर यह डारिन द्वारा सुझाए गए एक के माध्यम से गिरने में सक्षम होना चाहिए
स्टीव ग्रेट्रेक्स

2
यहां एक और महत्वपूर्ण बात यह है कि रूटिंग की इस शैली के साथ, आपको अनुमत HTTP विधियों (जैसे [HttpGet]) को निर्दिष्ट करने के लिए विशेषताओं का उपयोग करना चाहिए।
हिमालय गर्ग

1
क्या आप सुनिश्चित हैं कि आपको अन्य कार्यों का उपयोग करने की आवश्यकता है? क्या आपने वास्तव में फिट होने की कोशिश की है कि आप REST सम्मेलनों में क्या कर रहे हैं? यह अन्य कार्यों का उपयोग करने के लिए आवश्यक नहीं होना चाहिए।
नीको

1
@niico: कल्पना कीजिए कि आप एक गणना () विधि करना चाहते थे, जो तत्वों की संख्या प्राप्त करता है Get () वापस आ जाएगी। मैं यह नहीं देखता कि इसे कैसे प्राप्त किया जाए (), Get (id), Post (...), Put (...) या Delete (id)। और, ज़ाहिर है, वहाँ अनिश्चित रूप से अधिक संभव तरीके हैं जो मैं कल्पना कर सकता था।
जेन्स मैंडर

88

यह सबसे अच्छा तरीका है जो मैं अब तक सामान्य GEST विधियों के साथ-साथ समर्थन करते हुए अतिरिक्त GET विधियों को शामिल करने के लिए आया हूँ। निम्नलिखित मार्गों को अपने WebApiConfig में जोड़ें:

routes.MapHttpRoute("DefaultApiWithId", "Api/{controller}/{id}", new { id = RouteParameter.Optional }, new { id = @"\d+" });
routes.MapHttpRoute("DefaultApiWithAction", "Api/{controller}/{action}");
routes.MapHttpRoute("DefaultApiGet", "Api/{controller}", new { action = "Get" }, new { httpMethod = new HttpMethodConstraint(HttpMethod.Get) });
routes.MapHttpRoute("DefaultApiPost", "Api/{controller}", new {action = "Post"}, new {httpMethod = new HttpMethodConstraint(HttpMethod.Post)});

मैंने नीचे दिए गए परीक्षण वर्ग के साथ इस समाधान को सत्यापित किया। मैं अपने नियंत्रक में प्रत्येक विधि को सफलतापूर्वक हिट करने में सक्षम था:

public class TestController : ApiController
{
    public string Get()
    {
        return string.Empty;
    }

    public string Get(int id)
    {
        return string.Empty;
    }

    public string GetAll()
    {
        return string.Empty;
    }

    public void Post([FromBody]string value)
    {
    }

    public void Put(int id, [FromBody]string value)
    {
    }

    public void Delete(int id)
    {
    }
}

मैंने सत्यापित किया कि यह निम्नलिखित अनुरोधों का समर्थन करता है:

GET /Test
GET /Test/1
GET /Test/GetAll
POST /Test
PUT /Test/1
DELETE /Test/1

ध्यान दें कि यदि आपकी अतिरिक्त GET क्रियाएँ 'Get' से शुरू नहीं होती हैं, तो आप विधि में HttpGet विशेषता जोड़ना चाहते हैं।


1
अच्छा समाधान, क्या आप मुझे बता सकते हैं कि क्या मैं क्रियाओं putऔर deleteक्रियाओं को कॉन्फ़िगर करता हूं जैसे कि आपने किया था getऔर post, ठीक काम करेगा?
फेलिप ओरियानी

1
मेरी राय में इसे वेबएपीआई परियोजनाओं के लिए चूक में शामिल किया जाना चाहिए (शायद टिप्पणी की गई थी)। यह आपको एक ही समय में
वेबएपीआई

1
@FelipeOriani, मुझे नहीं लगता कि आप चाहते हैं या उन्हें कॉन्फ़िगर करने putया deleteक्रिया करने की आवश्यकता है क्योंकि उन अनुरोधों के लिए आमतौर पर एक आईडी पैरामीटर के साथ उस संसाधन की पहचान करना होगा जिसे आप उस ऑपरेशन को लागू करना चाहते हैं। एक deleteकॉल करने के लिए /api/fooएक त्रुटि जिसकी वजह से foo आप हटाने का प्रयास कर रहे हैं फेंक देना चाहिए? इसलिए DefaultApiWithId मार्ग को उन मामलों को ठीक से संभालना चाहिए।
nwayve

4
यह मेरे लिए बिल्कुल भी काम नहीं करता था। जब मुझे मूल GET करने का प्रयास किया गया तो त्रुटि संदेश मिला
मैट

पहले एक के लिए, DefaultApiWithId, क्या डिफॉल्ट को नए {id = RouteParameter.Optional} के बजाय शून्य नहीं होना चाहिए? क्या 'आईडी' की आवश्यकता नहीं है?
जॉनी ओशिका

22

मैं एमवीसी 4 दुनिया में हूं।

इसके लायक के लिए, मेरे पास एक साइटसपिक कंट्रोलर है, और मुझे एक कस्टम विधि की आवश्यकता है, जिसे इस तरह कहा जा सकता है:

http://localhost:9000/api/SitesAPI/Disposition/0

अंतिम पैरामीटर के लिए अलग-अलग मानों के साथ अलग-अलग डिस्पोजल के साथ रिकॉर्ड प्राप्त करने के लिए।

आखिरकार मेरे लिए क्या काम किया गया:

SitesAPIController में विधि:

// GET api/SitesAPI/Disposition/1
[ActionName("Disposition")]
[HttpGet]
public Site Disposition(int disposition)
{
    Site site = db.Sites.Where(s => s.Disposition == disposition).First();
    return site;
}

और यह WebApiConfig.cs में है

// this was already there
config.Routes.MapHttpRoute(
    name: "DefaultApi",
    routeTemplate: "api/{controller}/{id}",
    defaults: new { id = RouteParameter.Optional }
);

// this i added
config.Routes.MapHttpRoute(
    name: "Action",
    routeTemplate: "api/{controller}/{action}/{disposition}"
 );

जब तक मैं {id} को {id} बता रहा था, मेरा सामना हो रहा था:

{
"Message": "No HTTP resource was found that matches the request URI 'http://localhost:9000/api/SitesAPI/Disposition/0'.",
"MessageDetail": "No action was found on the controller 'SitesAPI' that matches the request."
}

जब मैंने इसका नाम बदलकर {डिस्पोजल} कर दिया तो यह काम करने लगा। तो जाहिरा तौर पर पैरामीटर नाम प्लेसहोल्डर में मूल्य के साथ मेल खाता है।

इसे और अधिक सटीक / व्याख्यात्मक बनाने के लिए इस उत्तर को संपादित करने के लिए स्वतंत्र महसूस करें।


पारितोषिक के लिए धन्यवाद। मैं भी आप जैसी ही गलती कर रहा था।
अभि

16

डिफ़ॉल्ट रूप से वेब एपीआई इस डिफ़ॉल्ट मार्ग को ओवरराइड करने के लिए एपीआई / {नियंत्रक} / {आईडी} के रूप में URL की अपेक्षा करता है। आप नीचे दिए गए दो तरीकों में से किसी के साथ रूटिंग सेट कर सकते हैं।

पहला विकल्प:

WebApiConfig.cs में मार्ग पंजीकरण के नीचे जोड़ें

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

नीचे के रूप में HttpGet और मापदंडों के साथ अपने एक्शन विधि को सजाने

[HttpGet]
public HttpResponseMessage ReadMyData(string param1,
                        string param2, string param3)

 {

// your code here

}

विधि से ऊपर कॉल करने के लिए url नीचे की तरह होगा

http: // localhost: [yourport] / API / MyData / ReadMyData param1 = मान 1 और param2 2 = मान और param3 = value3

दूसरा विकल्प नियंत्रक वर्ग के लिए मार्ग उपसर्ग जोड़ें और नीचे के रूप में HttpGet के साथ अपनी कार्रवाई विधि सजाने। इस स्थिति में किसी WebApiConfig.cs को बदलने की आवश्यकता नहीं है। इसमें डिफ़ॉल्ट रूटिंग हो सकती है।

[RoutePrefix("api/{controller}/{action}")]
public class MyDataController : ApiController
{

[HttpGet]
public HttpResponseMessage ReadMyData(string param1,
                        string param2, string param3)

{

// your code here

}

}

विधि से ऊपर कॉल करने के लिए url नीचे की तरह होगा

http: // localhost: [yourport] / API / MyData / ReadMyData param1 = मान 1 और param2 2 = मान और param3 = value3


मुझे दूसरा विकल्प बहुत पसंद है। क्या आप मुझे VB.net में इसका उपयोग करने का तरीका भी दिखा सकते हैं? बहुत बहुत धन्यवाद।
user1617676

12

यदि आप ASP.NET MVC 6 के साथ ASP.NET 5 का उपयोग कर रहे हैं , तो इनमें से अधिकांश उत्तर केवल इसलिए काम नहीं करेंगे क्योंकि आप सामान्य रूप से MVC को आपके लिए उपयुक्त मार्ग संग्रह बनाने देंगे (डिफ़ॉल्ट रीसेंट कन्वेंशन का उपयोग करके), जिसका अर्थ है आपको वसीयत में संपादित करने के लिए कोई कॉल नहीं मिलेगा ।Routes.MapRoute()

ConfigureServices()विधि द्वारा लाया Startup.csफ़ाइल निर्भरता इंजेक्शन ASP.NET 5 में निर्मित ढांचे के साथ MVC में दर्ज किए जाएंगे: इस तरह, जब आप कॉल ApplicationBuilder.UseMvc()कि कक्षा में बाद में, MVC ढांचे स्वचालित रूप से आपके अनुप्रयोग के लिए इन डिफ़ॉल्ट मार्गों जोड़ देगा। हम UseMvc()ढांचे के स्रोत कोड के भीतर विधि के कार्यान्वयन को देखकर हुड के पीछे क्या होता है, इस पर एक नज़र डाल सकते हैं :

public static IApplicationBuilder UseMvc(
    [NotNull] this IApplicationBuilder app,
    [NotNull] Action<IRouteBuilder> configureRoutes)
{
    // Verify if AddMvc was done before calling UseMvc
    // We use the MvcMarkerService to make sure if all the services were added.
    MvcServicesHelper.ThrowIfMvcNotRegistered(app.ApplicationServices);

    var routes = new RouteBuilder
    {
        DefaultHandler = new MvcRouteHandler(),
        ServiceProvider = app.ApplicationServices
    };

    configureRoutes(routes);

    // Adding the attribute route comes after running the user-code because
    // we want to respect any changes to the DefaultHandler.
    routes.Routes.Insert(0, AttributeRouting.CreateAttributeMegaRoute(
        routes.DefaultHandler,
        app.ApplicationServices));

    return app.UseRouter(routes.Build());
}

इसके बारे में अच्छी बात यह है कि यह ढांचा अब सभी कड़ी मेहनत को संभालता है, सभी नियंत्रक के कार्यों के माध्यम से पुनरावृत्ति करता है और उनके डिफ़ॉल्ट मार्गों को स्थापित करता है, इस प्रकार आपको कुछ अनावश्यक काम बचाता है।

बुरी बात यह है कि आप अपने स्वयं के मार्गों को कैसे जोड़ सकते हैं, इसके बारे में बहुत कम या कोई दस्तावेज नहीं है। सौभाग्य से, आप एक कन्वेंशन-बेस्ड और / या एट्रीब्यूट-बेस्ड एप्रोच (उर्फ अट्रेक्ट रूट्स ) का उपयोग करके आसानी से कर सकते हैं ।

कन्वेंशन के आधार पर

अपने Start..cs वर्ग में, इसे प्रतिस्थापित करें:

app.UseMvc();

इसके साथ:

app.UseMvc(routes =>
            {
                // Route Sample A
                routes.MapRoute(
                    name: "RouteSampleA",
                    template: "MyOwnGet",
                    defaults: new { controller = "Items", action = "Get" }
                );
                // Route Sample B
                routes.MapRoute(
                    name: "RouteSampleB",
                    template: "MyOwnPost",
                    defaults: new { controller = "Items", action = "Post" }
                );
            });

गुण आधारित

एमवीसी 6 के बारे में एक बड़ी बात यह है कि आप Controllerवर्ग को और / या Actionउपयुक्त RouteAttributeया HttpGet/ या HttpPostटेम्पलेट मानकों के साथ तरीकों से एक प्रति-नियंत्रक आधार पर मार्गों को परिभाषित कर सकते हैं , जैसे कि निम्नलिखित:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNet.Mvc;

namespace MyNamespace.Controllers
{
    [Route("api/[controller]")]
    public class ItemsController : Controller
    {
        // GET: api/items
        [HttpGet()]
        public IEnumerable<string> Get()
        {
            return GetLatestItems();
        }

        // GET: api/items/5
        [HttpGet("{num}")]
        public IEnumerable<string> Get(int num)
        {
            return GetLatestItems(5);
        }       

        // GET: api/items/GetLatestItems
        [HttpGet("GetLatestItems")]
        public IEnumerable<string> GetLatestItems()
        {
            return GetLatestItems(5);
        }

        // GET api/items/GetLatestItems/5
        [HttpGet("GetLatestItems/{num}")]
        public IEnumerable<string> GetLatestItems(int num)
        {
            return new string[] { "test", "test2" };
        }

        // POST: /api/items/PostSomething
        [HttpPost("PostSomething")]
        public IActionResult Post([FromBody]string someData)
        {
            return Content("OK, got it!");
        }
    }
}

यह नियंत्रक निम्नलिखित अनुरोधों को संभालेगा:

 [GET] api/items
 [GET] api/items/5
 [GET] api/items/GetLatestItems
 [GET] api/items/GetLatestItems/5
 [POST] api/items/PostSomething

यह भी ध्यान दें कि यदि आप दो दृष्टिकोण टॉगलर्स का उपयोग करते हैं, तो विशेषता-आधारित मार्ग (जब परिभाषित किया गया है) कन्वेंशन-आधारित को ओवरराइड करेगा, और वे दोनों ही निर्धारित डिफ़ॉल्ट मार्गों को ओवरराइड करेंगे UseMvc()

अधिक जानकारी के लिए आप मेरे ब्लॉग पर निम्न पोस्ट भी पढ़ सकते हैं ।


1
यह पूर्ण है! अन्य उत्तरों में से कोई भी वास्तव में नहीं था जो मुझे चाहिए था। लेकिन आपने मुझे बचा लिया :)
राजा आर्थर द थर्ड

क्या दूसरे पैरामीटर के रूप में पूर्व-परिभाषित मॉडल का उपयोग करने का एक तरीका है? उदाहरण के लिए, जब मैं इस तरह एक निश्चित उपयोगकर्ता पैचिंग हूँ: public IActionResult Patch(int id, [FromQuery] Person person), आने वाले सभी गुण अशक्त कर रहे हैं!
राजा आर्थर तीसरी बार

9

नामित कार्यों की लंबी चर्चा के लिए इस लेख को देखें। यह यह भी दर्शाता है कि आप "प्राप्त" के साथ क्रिया नाम को उपसर्ग करने के बजाय [HttpGet] विशेषता का उपयोग कर सकते हैं।

http://www.asp.net/web-api/overview/web-api-routing-and-actions/routing-in-aspnet-web-api


0

बस अपने WebAPIConfig.cs को bellow के रूप में संशोधित करें

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

फिर अपना API bellow के रूप में कार्यान्वित करें

    // GET: api/Controller_Name/Show/1
    [ActionName("Show")]
    [HttpGet]
    public EventPlanner Id(int id){}

0

वेब एपीआई 2 और बाद के संस्करण एक नए प्रकार के रूटिंग का समर्थन करते हैं, जिसे विशेषता रूटिंग कहा जाता है। जैसा कि नाम से पता चलता है, रूट को परिभाषित करने के लिए विशेषता रूटिंग विशेषताओं का उपयोग करती है। विशेषता रूटिंग आपको अपने वेब एपीआई में यूआरआई पर अधिक नियंत्रण देता है। उदाहरण के लिए, आप आसानी से यूआरआई बना सकते हैं जो संसाधनों के पदानुक्रम का वर्णन करते हैं।

उदाहरण के लिए:

[Route("customers/{customerId}/orders")]
public IEnumerable<Order> GetOrdersByCustomer(int customerId) { ... }

सही होगा और आपको WebApiConfig.cs में उदाहरण के लिए किसी अतिरिक्त कोड की आवश्यकता नहीं है। बस आपको यह सुनिश्चित करना है कि Web ApiConfig.cs में web api रूटिंग सक्षम है या नहीं, यदि आप नीचे सक्रिय नहीं कर सकते हैं:

        // Web API routes
        config.MapHttpAttributeRoutes();

आपको WebApiConfig.cs में कुछ अधिक करने या कुछ बदलने की आवश्यकता नहीं है। अधिक जानकारी के लिए आप इस लेख को देख सकते हैं ।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.