2014-09-14 12 views
11

Pracuję nad projektem ASP.NET WebAPI z podstawowymi operacjami CRUD. Projekt działa lokalnie i ma przykładową bazę danych znajdującą się w systemie Windows Azure.PUT i Delete nie działają z ASP.NET WebAPI i bazą danych na Windows Azure

Do tej pory Http GET i POST działają dobrze, dając mi 200 i 201. Ale walczę z DELETE i POST. Zmieniłem procedury obsługi w Web.config, usunięto WebDav, ale nic z tego nie zadziałało. Włączenie CORS i wszystkich atrybutów, takich jak [AcceptVerbs], nie działa.

Każdy pomysł, co robię źle?

Skrzypek Surowiec wyjściowy:

HTTP/1.1 405 Method Not Allowed 
Cache-Control: no-cache 
Pragma: no-cache 
Allow: GET 
Content-Type: application/json; charset=utf-8 
Expires: -1 
Server: Microsoft-IIS/8.0 
X-AspNet-Version: 4.0.30319 
X-SourceFiles: =?UTF-8?B?QzpcVXNlcnNcTWFyY1xPbmVEcml2ZVxEb2t1bWVudGVcRmlcVnNQcm9qZWt0ZVxONTIwMTQwODI1XE41XE41XGFwaVxwcm9kdWN0XDEwODM=?= 
X-Powered-By: ASP.NET 
Date: Sun, 14 Sep 2014 15:00:43 GMT 
Content-Length: 75 

{"Message":"The requested resource does not support http method 'DELETE'."} 

Web.config:

<system.webServer> 
    <validation validateIntegratedModeConfiguration="false" /> 
    <modules runAllManagedModulesForAllRequests="true"> 
     <remove name="WebDAVModule" /> 
    </modules> 
    <handlers> 
     <remove name="WebDAV" /> 
     <remove name="ExtensionlessUrlHandler-Integrated-4.0" /> 
     <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="GET,HEAD,POST,DEBUG,PUT" type="System.Web.Handlers.TransferRequestHandler" resourceType="Unspecified" requireAccess="Script" preCondition="integratedMode,runtimeVersionv4.0" /> 
    </handlers> 
</system.webServer> 

kontrolera:

public class ProductController : BaseApiController 
    { 
     public ProductController(IRepository<Product> repo) 
      : base(repo) 
     { 

     } 

     [HttpGet] 
     public IEnumerable<Product> Get() 
     { 
      //... 
     } 

     [HttpGet] 
     public Product Get(int id) 
     { 
      //... 
     } 

     [HttpPost] 
     public HttpResponseMessage Post([FromBody] Product product) 
     { 
      //... 
     } 

     [HttpPut] 
     public HttpResponseMessage Put(int productId, [FromBody] Product product) 
     { 
      //.. 
     } 

     [HttpDelete] 
     public HttpResponseMessage Delete(int productId) 
     { 
      //.. 
     } 

    } 

Routing & formatujących:

public static void Register(HttpConfiguration config) 
    { 
     // Web API configuration and services 
     // Configure Web API to use only bearer token authentication. 
     config.SuppressDefaultHostAuthentication(); 
     config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType)); 


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

     // Custom Formatters: 
     config.Formatters.XmlFormatter.SupportedMediaTypes.Remove(
      config.Formatters.XmlFormatter.SupportedMediaTypes.FirstOrDefault(t => t.MediaType == "application/xml")); 

     var jsonFormatter = config.Formatters.OfType<JsonMediaTypeFormatter>().First(); 
     jsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver(); 
    } 
} 
+0

Dlaczego wywołujesz routing atrybutów, ale konfigurujesz trasę produktu, korzystając z wcześniejszego sposobu konfiguracji trasy WebApi2? –

+0

To jest resztka i nie powinno tam być. Aktualizuję to. thx – oldsport

Odpowiedz

25

W końcu znalazłem to, co zepsułem. Nazewnictwo Id (productId) w obu metodach kontrolera (Post i Put) musi być takie samo jak w niestandardowym routingu (id). Kiedy zmieniłem go z productId na id, zarówno POST, jak i PUT działały w skrzypcach. Potem przełączyłem moje ustawienia Web.config na domyślne. To, co zmieniło:

Kontroler:

[HttpPut] 
    public HttpResponseMessage Put(int id, [FromBody] Product product) 
    { 
     //.. 
    } 

    [HttpDelete] 
    public HttpResponseMessage Delete(int id) 
    { 
     //.. 
    } 

Web.config:

<system.webServer> 
<modules> 
    <remove name="FormsAuthentication" /> 
</modules> 
<handlers> 
    <remove name="ExtensionlessUrlHandler-Integrated-4.0" /> 
    <remove name="OPTIONSVerbHandler" /> 
    <remove name="TRACEVerbHandler" /> 
    <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" /> 
</handlers> 

+0

Jeśli używasz domyślnego routingu wbudowanego, nazwa parametru musi również być "id". – RMorrisey

7

"atrybut routingu w ASP.NET Web API 2" (20-sty -2014) artykuł mówi nam następujące;

Routing to sposób, w jaki interfejs Web API dopasowuje URI do działania. Web API 2 obsługuje nowy typ routingu, nazywany routingiem atrybutów.

(Patrz: "Attribute Routing in ASP.NET Web API 2")

Tak, jak Web API 2, można także naprawić dodając atrybut trasach [Do omawiana metoda] z zastępczego o nazwie jak chcesz.

[HttpDelete] 
[Route("api/product/{productId}")] 
public HttpResponseMessage Delete(int productId) 
{ 
    if (values.Count > productId) { 
     values.RemoveAt(productId); 
    } 
} 

Testowałem to w moim własnym kodzie, ponieważ dostałem ten sam problem i zadziałało jak czar!

+0

W powyższym kodzie, dlaczego nie mógł productId być więcej niż values.Count i nadal być ważne. O ile widzę, użycie instrukcji if może zakończyć się niepowodzeniem. –

+0

@KeenanStewart Kod jest po prostu szybką i brudną próbką. Chodzi o routing atrybutów. –