0

我有一个架构,其中有许多可以配置的对象。我想要的 URL 示例如下:

/configuration/building/add
/configuration/building/edit/1
/configuration/group/add
/configuration/group/edit/1

我有一个配置控制器,但我如何拦截或处理building/add等等building/edit/1......如果是AddBuilding我可以简单地添加一个AddBuilding()函数,同样我如何让它工作configuration/building/edit/

4

4 回答 4

2

这是您可以为第一个执行的操作 - 打开您站点的 Global.asax.cs 文件并将其放在RegisterRoutes 标准MVC 包罗万象的路线(使用该路线的路线"{controller}/{action}/{id}")之前:

routes.MapRoute("AddBuilding", "configuration/building/add",
  new { controller = "Configuration", action = "AddBuilding" });

其他的将是相同的,但不同的名称(第一个参数)和操作,whislt 编辑路由但将包括{id}路由占位符和路由参数(但不是可选的 - 与 MVC 默认路由不同):

routes.MapRoute("EditBuilding", "configuration/building/edit/{id}",
  new { controller = "Configuration", action = "EditBuilding" });

通过保留id关闭路由默认值,我们将其设为必需。我假设这一点,因为我猜 Url/Building/Edit在逻辑上没有映射到任何东西。

作为一个侧面节点- 在你的 url 中包含动词并不真正符合 REST 方法,但是你并不是第一个这样做的人(我也包括在内)。也就是说 - 尝试保持它通常会让你的生活更轻松,因为你会发现你的控制器会更干净,你的路由表也会更干净,并且你的网站的 URL 空间会更小,层次更明显。最后一点是 -在开发时缩放网站很方便,但更重要的是它对 SEO 至关重要。

所以(我已经对这段代码进行了大量评论,希望足以提供一些知识!):

public class ConfigurationController{

  ////HTTP GET /Buildings
  /// DISPLAYS BUILDINGS
  public ActionResult Buildings(){
    //get model and return view that shows all buildings with perhaps a 
    //partial in that for creating a new one (or you can use another action)
    //The HTML form on that view will POST to the URL handled by the method below.
  }

  ////HTTP POST /Buildings
  /// CREATES A NEW BUILDING
  //use ActionName here to make this and the method above accessible through
  //the same URL
  [ActionName("Buildings")]
  [HttpPost]
  public ActionResult CreateBuilding(BuildingModel model){
    //validate the model, create the object and return the same
    //view as the Buildings() method above (after re-loading all the
    //buildings.  Or, you can issue a redirect, effectively transferring
    //control back to the method above.
  }

  ////HTTP GET /Configuration/Building/id
  ///DISPLAYS A BUILDING
  public ActionResult Building(int id){
    //get building and return view, which also contains Edit functionality
  }

  ////HTTP POST /Configuration/Building/id
  ///EDITS A BUILDING
  [HttpPost]
  public ActionResult Building(int id, BuildingModel model){
    //very similar to the CreateBuilding method - and again you might
    //either simply return a building view at the end, or redirect
    //to the method above.

    //Note that we don't need [ActionName] here because this and the
    //get method can have the same method names, because they are overloads
    //i.e. since they have different method signatures we can call them the same
    //thing in code.
  }
}

为了简短起见,我已经省略了小组内容,希望您能够从那里了解如何做到这一点。

有了这个,我们最多只需要 Global.asax.cs 中的两条路线 - 尽管我认为顺序很重要:

//handles both GET and POST to this URL, i.e. our view & edit operations
routes.MapRoute("IndividualBuilding", "/configuration/buildings/{id}", 
  new { controller = "Configuration", action = "Building" });
routes.MapRoute("Buildings", "/configuration/buildings",
  new { controller = "Configuration", action = "Buildings" });

现在我们使用 HTTP 动词来表示我们打算对特定请求执行的操作,并且我们的 URL 变得更加“合乎逻辑”。

另一个重构

如果您想变得“聪明”,您可以将建筑物和团体归为两条路线

//handles both GET and POST to this URL, i.e. our view & edit operations
routes.MapRoute("Individual", "/configuration/{controller}/{id}", 
  new { controller = "Configuration", action = "List" });
//again, handles GET and POST
routes.MapRoute("Collection", "/configuration/{controller}",
  new { controller = "Configuration", action = "Single" });

现在你可以像我上面展示的那样做建筑物和组控制器,但是用 和 替换(记住Buildings第二种ActionName方法的属性)。ListBuildingSingle

最后要考虑的一件事是,由于默认的 MVC 路由:

routes.MapRoute("Default", "{controller}/{action}/{id}", 
  new { controller = "Default", action="Home", id = UrlParameter.Optional });

您的两个控制器仍然可以通过/Buildings/Single/1/Groups例如路由。这是一个小问题(欺骗内容不是很好的 SEO),但它可能是人们可以用来嗅探您的网站的东西。

如果您绝对想阻止这种其他 url 格式;您可以取出默认路由,这意味着您必须明确路由其他可能已经工作的东西(不是一个大问题)。

或者你可以使用一个小技巧,让它变得更加困难:使用[ActionName]路由名称中不允许通过 IIS 的字符的显式属性 - 例如":Single"or ":List",然后从几个代码块中相应地调整我们的两条路由。

于 2012-07-27T12:59:07.040 回答
1

因此,首先您可以创建一个控制器操作AddBuilding(),如您所暗示的那样。

然后在您的Global.asax文件中的RegisterRoutes方法中,您可以添加如下路线:

routes.MapRoute(
   "AddBuilding", // Route name
   "configuration/building/add", // URL with parameters
   new { controller = "Configuration", action = "AddBuilding" }
);

您不应该因为您的默认路由映射,您可能仍然能够使用“/configuration/addbuilding”访问该页面。

您编辑一个将是类似的期望您将要映射此ID值:

routes.MapRoute(
   "EditBuilding", // Route name
   "configuration/building/edit/{id}", // URL with parameters
   new { controller = "Configuration", action = "AddBuilding", id = UrlParameter.Optional }
);

我认为您需要使用默认MapRoute设置添加此代码,以确保不优先

于 2012-07-27T13:04:13.117 回答
0

另一种方法是创建一个配置 MVC area,然后在其中创建一个建筑物和controllerArea

于 2012-07-27T13:06:08.700 回答
0

您可以通过 ASP.NET MVC 5 中的属性路由来做到这一点。如下所示;

// eg: /reviews
[Route(“reviews”)]
public ActionResult Index() { … }
// eg: /reviews/5
[Route(“reviews/{reviewId}”)]
public ActionResult Show(int reviewId) { … }
// eg: /reviews/5/edit
[Route(“reviews/{reviewId}/edit”)]
public ActionResult Edit(int reviewId) { … }

您也可以为同一个控制器添加多个路由。详情请查看这里

于 2016-02-29T19:53:34.710 回答