मेरे पास उत्पाद नियंत्रक और स्वामी नियंत्रक हैं:

public class ProductsController : ApiController
{

    //constructor is here

    // GET /api/products
    public IHttpActionResult GetProducts()
    {
        return Ok(new ApiResponse());
    }

    // GET /api/products/{productCode}
    [HttpGet, Route("api/products/{productCode}")]
    public IHttpActionResult GetProductByCode(string productCode)
    {
         return Ok(new ApiResponse());
    }

    // POST /api/products
    public IHttpActionResult PostProduct(Product product /*my class*/)
    {
        return CreatedAtRoute("DefaultApi", new { id = product.Id }, product);
    }
}

यह पूरी तरह से काम करता है। लेकिन अब मैं दूसरा नियंत्रक बनाता हूं और वही काम करता हूं लेकिन POST विधि का प्रयास करते समय मुझे त्रुटि मिलती है। अन्य विधियां अच्छी तरह से काम करती हैं!

आइए पहले कोड पर एक नज़र डालें:

public class OwnersController : ApiController
{
    // constructor

    // GET /api/owners/{label}
    // GET /api/owners/{label}?skip=1&take=4
    [Route("api/owners/{label}")]
    public IHttpActionResult GetOwnersExamples(string label, int skip=0, int take=10)
    {
        return Ok(new ApiResponse());
    }
    // POST /api/owners/{productCode}
    //[HttpPost]
    [Route("api/owners/{productCode}"/*, Name = "CreateOwner"*/)]
    public IHttpActionResult PostOwner(string productCode, Owner owner)
    {
        return CreatedAtRoute("DefaultApi", new { id = Owner.Id }, owner);
    }  
}

त्रुटि संदेश:

UrlHelper.Link अशक्त नहीं लौटना चाहिए


मेरा रूटकॉन्फ़िगर:

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

जैसा कि मैं समस्या को समझता हूं कि CreateAtRoute विधि को एक और RouteName मिलना चाहिए। जैसा कि आप देख सकते हैं कि मैं रूट नाम पैरामीटर (अभी टिप्पणी की गई) जोड़कर समस्या का समाधान कर सकता हूं और "DefaultApi" को "CreateOwner" से बदल सकता हूं लेकिन यह एक हैक जैसा दिखता है। मेरा मानना ​​है कि Name Property से बचने का एक और तरीका है।

पी.एस. ऐसा लगता है कि मेरा वेब एपीआई केवल पहले नियंत्रक (उत्पाद नियंत्रक) को देख सकता है - अगर मैं स्पष्ट रूट [Route("...")]...

0
Mikhail_Sam 7 फरवरी 2018, 15:19
त्रुटि किस लाइन पर होती है? क्या आप एक स्टैक ट्रेस प्रदान कर सकते हैं?
 – 
NightOwl888
8 फरवरी 2018, 01:12

2 जवाब

सबसे बढ़िया उत्तर

मैं अगले चरणों का उपयोग करके समस्या का समाधान करता हूं:

  1. नियंत्रक के लिए सभी [RoutePrefix] हटाएं - उन्हें डिफ़ॉल्ट रूप से काम करने दें - यह सरल अनुरोधों के लिए पूरी तरह से काम करता है।
  2. महत्वपूर्ण: डुप्लीकेट के लिए सभी विधियों की जांच करें! समस्या यह थी कि मेरे पास मार्गों api/controller/{label} और api/controller/{parameter} के साथ 2 विधियां थीं - यह समझ में नहीं आता कि उनमें से कौन सा डिफ़ॉल्ट रूप से उपयोग करना है। (या स्पष्ट यूरी का प्रयोग करें: api/controller?label=1)
  3. महत्वपूर्ण: बहुत सारे जटिल प्रकारों को एपीआई विधियों में डालने से बचें - उनके लिए रैपर बनाएं और केवल एक पैरामीटर डालें!

इन सभी क्रियाओं ने मुझे अतिरिक्त विशेषताओं को हटाने और विधियों को और अधिक पठनीय बनाने की अनुमति दी।

यहाँ परिणाम है:

public IHttpActionResult PostOwner(OwnerWrapper modelWrapper)
{
    string productCode = modelWrapper.Product.Code;
    Owner owner = modelWrapper.Owners[0];

    return CreatedAtRoute("DefaultApi", new { id = Owner.Id }, owner);
}

यह सिर्फ परीक्षण का मामला है, इसलिए हम देख सकते हैं कि productCode का कभी भी उपयोग नहीं किया जाता है, लेकिन मेरा वास्तविक अहसास अधिक कठिन है।

1
Mikhail_Sam 8 फरवरी 2018, 17:17

जैसा कि मैं समस्या को समझता हूं कि CreateAtRoute विधि को एक और रूटनाम प्राप्त करना होगा। जैसा कि आप देखते हैं कि मैं रूट नाम पैरामीटर (अभी टिप्पणी की गई) जोड़कर समस्या का समाधान कर सकता हूं और "DefaultApi" को "CreateOwner" से बदल सकता हूं लेकिन यह एक हैक जैसा दिखता है। मेरा मानना ​​​​है कि नाम संपत्ति से बचने का एक और तरीका है।

आपकी समझ लगभग सही है। हालाँकि आपको एक नाम निर्दिष्ट करना चाहिए जो वर्तमान मार्ग के लिए नहीं है, बल्कि उस एक के लिए है जो निर्मित संसाधन की ओर इशारा करता है। CreatedAtRoute प्रतिक्रिया भरता है Location हैडर नव निर्मित संसाधन के लिए एक GET-सक्षम URI होना चाहिए।

यहां एक कामकाजी नमूना है:

[HttpGet]
[Route("api/owners/{id}", Name = "GetOwnerById")]
public IHttpActionResult GetOwner(int id)
{
    //  Obtain the owner by id here
    return Ok(new ApiResponse());
}

[HttpPost]
[Route("api/owners/{productCode}"/*, Name = "CreateOwner"*/)]
public IHttpActionResult PostOwner(string productCode, Owner owner)
{
    return CreatedAtRoute("GetOwnerById", new { id = owner.Id }, owner);
}

(नोट: इस उदाहरण को काम करने के लिए, आपको GetOwnersExamples कार्रवाई पर टिप्पणी करनी चाहिए, अन्यथा एकाधिक कार्रवाई आपके GET अनुरोध से मेल खाएँगी।)

आपने कहा कि यह हैक जैसा दिखता है, लेकिन ऐसा नहीं है। CreatedAtRoute तर्क के रूप में मार्ग का नाम लेता है और आपको इसे प्रदान करना चाहिए। अन्यथा कैसे उचित कार्रवाई का चयन किया जाएगा और Location हेडर बनाया जाएगा?

2
CodeFuller 8 फरवरी 2018, 09:13
योगदान के लिए धन्यवाद! आपका उत्तर पढ़कर मुझे समाधान मिल गया। फिर भी उत्तर दूसरा है, जानकारी की कमी के कारण आप मुझे नहीं दे सके :)
 – 
Mikhail_Sam
8 फरवरी 2018, 17:20