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

Sat*_*tal 3 asp.net-mvc routing asp.net-mvc-areas

我正在玩它们内部的区域和路由.我想要实现的是能够拥有一个看起来像这样的URL;

PracticeAdmin/Practice/[Practice Name]
Run Code Online (Sandbox Code Playgroud)

然后,我可以添加编辑和删除等内容.

过去通过在操作中添加此注释来处理区域时,我已经实现了这一点

[Route("PracticeAdmin/Practices/{practiceName}")]
public ActionResult Details(string practiceName)
Run Code Online (Sandbox Code Playgroud)

这会生成我想要的URL.我遇到的问题是,当我在使用区域时尝试这样做时,我得到的链接看起来像这样;

PracticeAdmin/Practices?practiceName=Practice1
Run Code Online (Sandbox Code Playgroud)

这不是我要找的.

我用来尝试生成这个的代码是

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" }
            );
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

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" }
            );
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我在这里调用了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);
        }
        ...
Run Code Online (Sandbox Code Playgroud)

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

Index.cshtml片段

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

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

摘要

我不知道为什么我尝试在一个区域中创建一个ActionLink时没有出现我所指定的路由,所以我想知道是否有人能够指出我如何能够解决这个问题并获得看看我想要它的URL?

Sat*_*tal 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" }
        );
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

不幸的是,仅凭这一点并没有解决问题,我也不得不对Controller进行一些修改.修改是像这样向Controller 添加RoutePrefixRouteArea属性;

[RouteArea("PracticeAdmin")]
[RoutePrefix("Practice")]
public partial class PracticesController : Controller
{
Run Code Online (Sandbox Code Playgroud)

这样做的另一个好处是,当通过Route属性指定特定操作的路径时,您不必再指定这些部分,因此最初操作的签名看起来像这样;

// GET: PracticeAdmin/Practices/{practiceName}/Members
[Route("PracticeAdmin/Practices/{practiceName}/Members")]
public virtual ActionResult Members(string practiceName)
{
Run Code Online (Sandbox Code Playgroud)

它现在看起来像这样;

// GET: PracticeAdmin/Practices/{practiceName}/Members
[Route("{practiceName}/Members")]
public virtual ActionResult Members(string practiceName)
{
Run Code Online (Sandbox Code Playgroud)

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