ASP.NET MVC路由参数不适用于区域

时间:2014-09-21 19:19:58

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

我正在玩其中的区域和路由。我想要实现的是能够拥有这样的URL;

PracticeAdmin/Practice/[Practice Name]

然后我可以将编辑和删除等内容添加到。

的末尾

过去我通过在动作

中添加此注释来处理区域时已经实现了这一点
[Route("PracticeAdmin/Practices/{practiceName}")]
public ActionResult Details(string practiceName)

这会生成我想要的网址。我遇到的问题是,当我尝试使用区域时,我会得到这样的链接;

PracticeAdmin/Practices?practiceName=Practice1

这不是我想要的。

我用来尝试生成此代码的代码是

PracticeAdminAreaRegistration.cs

using System.Web.Mvc;

namespace TrainingPortal.Areas.PracticeAdmin
{
    public class PracticeAdminAreaRegistration : AreaRegistration 
    {
        public override string AreaName 
        {
            get 
            {
                return "PracticeAdmin";
            }
        }

        public override void RegisterArea(AreaRegistrationContext context) 
        {
            context.MapRoute(
                "PracticeAdmin_default",
                "PracticeAdmin/{controller}/{action}/{id}",
                new { action = "Index", id = UrlParameter.Optional },
                new[] { "TrainingPortal.Areas.PracticeAdmin.Controllers" }
            );
        }
    }
}

RouteConfig.cs

namespace TrainingPortal
{
    public class RouteConfig
    {
        public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

            routes.MapMvcAttributeRoutes();

            routes.MapRoute(
                name: "Default",
                url: "{controller}/{action}/{id}",
                defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional },
                namespaces: new[] { "TrainingPortal.Controllers" }
            );
        }
    }
}

我在这里调用了MapMvcAttributeRoutes,我认为这应该意味着即使在区域内也可以注册路由。我也尝试在PracticeAdminAreaRegistration中放置必要的代码来做同样的事情而没有效果。

PracticeAdminController.cs

namespace TrainingPortal.Areas.PracticeAdmin.Controllers
{
    public partial class PracticesController : Controller
    {
        private TpContext db = new TpContext();

        // GET: PracticeAdmin/Practices
        public virtual ActionResult Index()
        {
            return View(db.Practices.ToList());
        }

        [Route("PracticeAdmin/Practice/{practiceName}")]
        public virtual ActionResult Details(string practiceName)
        {
            if (string.IsNullOrWhiteSpace(practiceName))
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
            Practice practice = db.Practices.FirstOrDefault(m => m.PracticeName.ToLower() == practiceName);
            if (practice == null)
            {
                return HttpNotFound();
            }
            return View(practice);
        }
        ...

显然它继续使用其他方法,但它们都遵循与此相同的方法。

Index.cshtml代码段

@Html.ActionLink("Delete", MVC.PracticeAdmin.Practices.Delete(item.PracticeName))
@Html.ActionLink("Delete2", "Delete", new { practiceName = item.PracticeName })

在PracticeAdminArea / Views / Practices / Index.cshtml中,我尝试过使用T4MVC和普通的ActionLink方法生成完全相同的链接(不出所料)。

摘要

我不知道为什么在尝试在某个区域创建ActionLink时,我指定的路径没有出现,所以我想知道是否有人能够指出我如何解决这个问题的方向并获取URL以了解我希望如何?

1 个答案:

答案 0 :(得分:5)

经过一段时间的游戏,我设法让它发挥作用。我最终解决问题的方法是在调用AreaRegistration.RegisterAllAreas()后调用RouteConfig.RegisterRoutes() MapMvcAttributeRoutes()

public class RouteConfig
{
    public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

        routes.MapMvcAttributeRoutes();

        AreaRegistration.RegisterAllAreas();

        routes.MapRoute(
            name: "Default",
            url: "{controller}/{action}/{id}",
            defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional },
            namespaces: new[] { "TrainingPortal.Controllers" }
        );
    }
}

由于你不允许两次调用这个方法(或者你因为你已经注册了两次相同的路由名而感到非常不安)我从Global.asax中移除了对AreaRegistration.RegisterAllAreas()的调用,使它看起来像这;

public class MvcApplication : System.Web.HttpApplication
{
    protected void Application_Start()
    {
        GlobalConfiguration.Configure(WebApiConfig.Register);
        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
        RouteConfig.RegisterRoutes(RouteTable.Routes);
        BundleConfig.RegisterBundles(BundleTable.Bundles);
    }
}

不幸的是,仅此一项并未解决问题,我还必须对Controller进行一些修改。修改是将RoutePrefixRouteArea属性添加到Controller中,如下所示;

[RouteArea("PracticeAdmin")]
[RoutePrefix("Practice")]
public partial class PracticesController : Controller
{

这具有额外的好处,当通过Route属性指定特定操作的路由时,您不必再指定这些部分,因此最初操作的签名看起来像这样;

// GET: PracticeAdmin/Practices/{practiceName}/Members
[Route("PracticeAdmin/Practices/{practiceName}/Members")]
public virtual ActionResult Members(string practiceName)
{

现在看起来像这样;

// GET: PracticeAdmin/Practices/{practiceName}/Members
[Route("{practiceName}/Members")]
public virtual ActionResult Members(string practiceName)
{

完成所有这些更改后,网站的行为符合预期。