2010-01-28 18 views
8

Sadece bu URL'yi bir POST kabul eden bir denetleyicisi var:ASP.NET MVC yönlendirmesinde HttpMethodConstraint ile nasıl özel bir kısıtlama kullanırım?

POST http://server/stores/123/products 

SONRASI content-type application/json olmalıdır, bu nedenle bu benim yönlendirme tablosunda ne var:

routes.MapRoute(null, 
       "stores/{storeId}/products", 
       new { controller = "Store", action = "Save" }, 
       new { 
         httpMethod = new HttpMethodConstraint("POST"), 
         json = new JsonConstraint() 
        } 
       ); 

nerede JsonConstraint: Ben rotayı kullandığınızda

public class JsonConstraint : IRouteConstraint 
{ 
    public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection) 
    { 
     return httpContext.Request.ContentType == "application/json"; 
    } 
} 

, ben Yasak bir 405 olsun:

Ben json = new JsonConstraint() kısıtlamasını kaldırırsanız

The HTTP verb POST used to access path '/stores/123/products' is not allowed

Ancak, iyi çalışıyor. Neyi yanlış yaptığımı bilen var mı?

+0

size jQuery pasajı gönderebilir Lütfen? Bazı başka testler çalıştırıyorum ve ContentType'ın "application/xml" olarak gösterildiğini gösteriyor. –

+0

Test etmek için 'REST Client' adlı bir Firefox eklentisi kullanıyorum. –

cevap

8

Bunu bir yoruma ekledim ancak yeterli alan yok.

Özel bir kısıtlama yazarken, routeDirection parametresini denetlemek ve mantığınızın yalnızca doğru zamanda çalıştığından emin olmak çok önemlidir.

Bu parametre, kısıtlamanızın gelen bir isteği işlerken veya bir kullanıcı URL oluştururken çalıştırılmakta (örneğin, Html.ActionLink gibi) çalıştırıldığını bildirir. Senin durumunda

Sana "eğer" dev tüm eşleştirme kodu koymak istiyorum düşünüyorum:

public bool Match(HttpContextBase httpContext, Route route, 
    string parameterName, RouteValueDictionary values, 
    RouteDirection routeDirection) 
{ 
    if (routeDirection == RouteDirection.IncomingRequest) { 
     // Only check the content type for incoming requests 
     return httpContext.Request.ContentType == mimeType; 
    } 
    else { 
     // Always match when generating URLs 
     return true; 
    } 
} 
+0

İyi bir yanıt, ama 'ContentType' yerine 'Accept' kullanmamalı mıyız? http://stackoverflow.com/a/15898503/1804678 – Jess

+0

@ Özgün soru 'ContentType' öğesinden bahsetmişti. 'ContentType 'isteğin gövdesinin biçimini gösterirken,' Accept 'başlığı, yanıtın gövdesinden * istenen * olduğunu gösterir. – Eilon

4

JsonConstraint hatalarını ayıklar ve içerik türünün ne olduğunu görürüm.

Herhangi bir nedenle, application/json olmayabilir.

O RFC MIME türü olduğunu biliyorum ama bir previous question burada belirtildiği gibi, (örneğin text/x-json gibi) benim dönemimde etrafında yüzen birkaç başka gördük.

Ayrıca, hiç bir ContentType kısıtlaması görmedim, bu yüzden işe yarayıp yaramadığını görmek isterim. Hatalı olması durumunda diğer MIME türleriyle denediniz mi?

Son olarak, yalnızca bir JsonConstraint olması yerine, genel bir ContentTypeConstraint oluşturur.

Güncelleme: Birlikte ContentTypeConstraint kodunu kullanan bir rotada hızlı bir WebRequest yöntemi çaldı ve bu düzgün çalışması gibi görünüyor

.

Enum

public enum ConstraintContentType 
{ 
    XML, 
    JSON, 
} 

Bu aranmak

public class ContentTypeConstraint : IRouteConstraint 
{ 
    private string mimeType; 

    public ContentTypeConstraint(ConstraintContentType constraintType) 
    { 
    //FYI: All this code could be redone if you used the Description attribute, and a ToDescription() method. 
    switch (constraintType) 
    { 
     case ConstraintContentType.JSON: 
     mimeType = "application/json"; 
     break; 
     case ConstraintContentType.XML: 
     mimeType = "text/xml"; 
     break; 
     default: 
     mimeType = "text/html"; 
     break; 
    } 
    } 

    public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection) 
    { 
    //As suggested by Eilon 
    if (routeDirection == RouteDirection.UrlGeneration) 
     return true; 

    return httpContext.Request.ContentType == mimeType; 
    } 
} 

Kısıtlama sınıfı olarak, sizin örnek kullanarak:

contentType = new ContentTypeConstraint(ConstraintContentType.JSON) 

kısıtlamayı Bu edilmiş yeniden kullanılabilir jul Sadece JSON'dan daha fazla. Ayrıca, enum sınıfında açıklama öznitelikleri kullanırsanız, geçiş durumu da yapılabilir.

+0

Güncelleme ve blog gönderisi için teşekkürler. –

+0

@Jess It. Ne yazık ki blogumu birkaç yıl önce aldım, ama cevabın et ve kemikleri hala geçerli (oldukça eski). –