MVC创建自定义路由

时间:2013-11-05 13:53:09

标签: asp.net-mvc asp.net-mvc-4 asp.net-mvc-routing

我的控制器中有以下内容:

    public ActionResult Details(string name)
    {
        Student student = db.Students.FirstOrDefault(x => x.FirstName == name);
        if (student == null)
        {
            return HttpNotFound();
        }
        return View(student);
    }

    // GET: /Student/Details/5
    public ActionResult Details(int? id)
    {
        if (id == null)
        {
            return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
        }
        Student student = db.Students.Find(id);
        if (student == null)
        {
            return HttpNotFound();
        }
        return View(student);
    }

RouteConfig.cs:

        // /Student/Details/Id
        routes.MapRoute(
            name: "StudentDetailsId",
            url: "{Student}/{Action}/{id}",
            defaults: new { controller = "Student", action = "Details", id = UrlParameter.Optional },
            constraints: new { id = @"\d+" }
        );

        // /Student/Details/Name
        routes.MapRoute(
            name: "StudentDetailsName",
            url: "{Student}/{Details}/{name}",
            defaults: new { controller = "Student", action = "Details" }
        );

        // /Student/Name
        routes.MapRoute(
            name: "StudentName",
            url: "{Student}/{name}",
            defaults: new { controller = "Student", action = "Details" }
        );

所以我想拥有相同的动作名称,但是使用id:int或string获取。

但是我得到以下内容:

The current request for action 'Details' on controller type 'StudentController' is ambiguous between the following action methods:
System.Web.Mvc.ActionResult Details(System.String) on type MySuperAwesomeMVCApp.Controllers.StudentController
System.Web.Mvc.ActionResult Details(System.Nullable`1[System.Int32]) on type MySuperAwesomeMVCApp.Controllers.StudentController

1 个答案:

答案 0 :(得分:2)

控制器:

public ActionResult DetailsByName(string name)
{
    Student student = db.Students.FirstOrDefault(x => x.FirstName == name);
    if (student == null)
    {
        return HttpNotFound();
    }
    return View(student);
}

// GET: /Student/Details/5
public ActionResult DetailsById(int? id)
{
    if (id == null)
    {
        return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
    }
    Student student = db.Students.Find(id);
    if (student == null)
    {
        return HttpNotFound();
    }
    return View(student);
}

路线:

 // /Student/Details/Id
    routes.MapRoute(
        name: "StudentDetailsId",
        url: "{controller}/{action}/{id}",
        defaults: new { controller = "Student", action = "DetailsById", id = UrlParameter.Optional },
        constraints: new { id = @"\d+" }
    );

    // /Student/Details/Name
    routes.MapRoute(
        name: "StudentDetailsName",
        url: "{controller}/{action}/{name}",
        defaults: new { controller = "Student", action = "DetailsByName" }
    );

    // /Student/Name
    routes.MapRoute(
        name: "StudentName",
        url: "{controller}/{name}",
        defaults: new { controller = "Student", action = "DetailsByName" }
    );

在MVC中,最多只能有2个具有相同名称的方法,当你这样做时,其中一个必须是GET而另一个必须是POST。

不,在给定一组路由数据的情况下,MVC无法确定要调用的操作方法。虽然您的方法是有效的C#重载,但MVC的操作方法选择器不是强类型的。我之前已回答过这个问题,让我查一下链接......

<强>更新

以下是链接:https://stackoverflow.com/a/10668537/304832

另一次更新

我只是提起这件事,因为当我回答其他路线问题时,其他人已经感谢我提及它了......看看AttributeRouting.NET。它是如此之大,以至于它是MVC5最受关注的功能,虽然它最初是一个开源的项目,没有理由不能在MVC4中使用它。只需下载NuGet包。使用此库,您无需使用MapRoute。你的行动方法如下:

// GET: /Students/Details/5
[GET("students/details/{id:int}", ControllerPrecedence = 1)]
public ActionResult DetailsById(int? id)
{
    if (id == null)
    {
        return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
    }
    Student student = db.Students.Find(id);
    if (student == null)
    {
        return HttpNotFound();
    }
    return View(student);
}

// GET: /Students/Details/Albert+Einstein
// or GET: /Students/Albert+Einstein
[GET("students/{name}", ActionPrecedence = 1)]
[GET("students/details/{name}")]
public ActionResult DetailsByName(string name)
{
    Student student = db.Students.FirstOrDefault(x => x.FirstName == name);
    if (student == null)
    {
        return HttpNotFound();
    }
    return View(student);
}

不需要MapRoute或神秘的正则表达式约束。您只需确保您的int方法具有优先权,以便MVC不会尝试将数字传递到您的方法中string