2010-08-04 66 views
0

我正在尝试将REST-行为写入到我的ASP.NET MVC2应用中,但我很难弄清楚如何使路由按我的意思工作。在ASP.NET MVC中基于请求的数据类型的路由

我想我的路由的工作是这样的:

/Users/Get/1 <- returns a regular HTML-based reply 
/Users/Get.xml/1 <- returns the data from Get as XML 
/Users/Get.json/1 <- returns the data as JSon 

我试过设置路线是这样的:

routes.MapRoute("Rest", 
"{controller}/{action}{format}/{id}" (...) 

但抱怨我需要之间的分隔符{}行动和{格式}

还执行以下操作:

routes.MapRoute("Rest", 
    "{controller}/{action}.{format}/{id}" (...) 

使得/ Users/Get/1无效(它必须是/Users/Get./1,这是不可接受的)

有什么建议吗?

-------------编辑-------------------------------- ----

我有一个解决方案的权利,但我真的不喜欢它:

routes.MapRoute(
      "DefaultWithFormat", // Route name 
      "{controller}/{action}.{format}/{id}", // URL with parameters 
      new { controller = "Home", action = "Index", format = "HTML", id = UrlParameter.Optional } // Parameter defaults 
     ); 
     routes.MapRoute(
      "Default", // Route name 
      "{controller}/{action}/{id}", // URL with parameters 
      new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults 
     ); 

这工作既/Users/Get.whateverFormat/1也/用户/获取/ 1

这样做的原因是,当我刚刚执行/ Users/Get/1(不带.format)时,它会跳过第一个路径,然后转到下一个不包含格式的路径。 要处理我已经创建了一个ActionFilterAttribute返回并覆盖这样的OnActionExecuted方法:

var type = filterContext.RouteData.Values["format"]; 
if (type != null && attributes != null) 
{ 
    if (type == "HTML") return; 
    if (type.ToString().ToLower() == "xml" && attributes.Any(a => a.AllowedTypes.Any(a2 => a2 == ResponseType.XML))) 
    { 
     filterContext.Result = new XmlResult(filterContext.Controller.ViewData.Model); 
     filterContext.HttpContext.Response.Clear(); 
     filterContext.HttpContext.Response.ContentType = "text/xml"; 
     return; 
    } 
    if (type.ToString().ToLower() == "json" && attributes.Any(a => a.AllowedTypes.Any(a2 => a2 == ResponseType.JSON))) 
    { 
     filterContext.Result = new JsonResult() { Data = (filterContext.Controller.ViewData.Model), JsonRequestBehavior = JsonRequestBehavior.AllowGet }; 
     filterContext.HttpContext.Response.Clear(); 
     filterContext.HttpContext.Response.ContentType = "text/json"; 
     return; 
    } 
} 

而且我也有一个ResponseTypeAttribute,让我来装饰什么的返回类型,他们应该让操作:

[AttributeUsage(AttributeTargets.All, Inherited = false, AllowMultiple = true)] 
public sealed class ResponseTypeAttribute : Attribute 
{ 
    List<ResponseType> allowedTypes; 

    public List<ResponseType> AllowedTypes 
    { 
     get { return allowedTypes; } 
     set { allowedTypes = value; } 
    } 

    public ResponseTypeAttribute(params ResponseType[] allowedTypes) 
    { 
     this.allowedTypes = new List<ResponseType>(); 
     this.allowedTypes.AddRange(allowedTypes); 
    } 


} 

public enum ResponseType 
{ 
    XML, JSON 
} 

XmlResult只是一个简单的对象序列化器。

回答

0

Brad Wilson与标题高级ASP.NET MVC2进行了一次谈话,他展示了一个示例,说明如何实现您想要的功能。您也可以下载幻灯片和示例代码在这里:

http://bradwilson.typepad.com/blog/talks.html

(这是页面上的第一讲,如果我记得很清楚宁静的URL是在讲第一个主题)

+0

并没有真正帮助我,因为幻灯片显示:“演示 - 支持类似REST的URL”,并且示例代码中没有示例:) – 2010-08-04 08:09:42

+0

我已经看过这段视频:http://events.boostweb20的.com /活动/ SeattleCodeCamp2010 /#状态= sessionCode%242003-4。如果你有时间看看它。 :)它确实显示了关于宁静的URL的演示...... – apolka 2010-08-04 09:04:10

+0

现在,这是一个非常甜蜜的解决方案! :D – 2010-08-04 10:30:28

0

有无您尝试设置的html的默认值?

0

也许这是一个选项(使用'/'而不是''。“):

routes.MapRoute(
     "Rest1", 
     "Users/Get/{format}/{id}", 
     new { controller = "Users", action = "Get", format = "HTML" } 
     ); 

然后

public class UsersController : Controller { 
    public ActionResult Get(string format, int id) { 
     switch (format) { 
     case "json": 
      break; 
     case "xml": 
      break; 
     default: 
      break; 
     } 
     return new ContentResult(); // Or other result as required. 
    } 
} 
+0

当然,但这不是我的问题;) – 2010-08-04 08:48:44

0

另一个想法:

routes.MapRoute(
    "Rest1", 
    "Users/Get/{id}.{format}", 
    new { controller = "Users", action = "Get", format = "HTML" } 
    ); 

然后在CONTROLER方法添加一些代码retreaving ID和格式

+0

那么/用户/获取/ 1不会工作...我需要写“/用户/获取/ 1”。为了路线工作... – 2010-08-04 08:35:14