简体   繁体   English

.NET MVC 路由 - 绑定 2 个 routeMap 参数

[英].NET MVC Routing - bind 2 routeMap parameters

I need to parse an url like the following我需要像下面这样解析一个 url

/controller/action/subaction/id

At the moment i'm using a switch on subaction to see what actually needs to be done.目前我正在使用子动作开关来查看实际需要做什么。 EG:例如:

    public ActionResult Members(string subaction, long id=0)
    {
        switch (subaction)
        {
            case "Details":
                var member = _payment.GetMember(id);
                return View("Members_details", member);
            default:
                var members = _payment.GetMembers().ToList();
                return View("Members_list", members);
        }
    }

This works, but i'd rather have seperate actions for each event, directly accessed from the route.这可行,但我宁愿对每个事件都有单独的操作,直接从路由访问。 If possible I would like to combine the action and subaction in the routemap to access the right action.如果可能的话,我想结合路由图中的动作和子动作来访问正确的动作。

  • /controller/action/ would call action() /controller/action/ 会调用 action()
  • /controller/action/subaction would call action_subaction() /controller/action/subaction 会调用 action_subaction()
  • /controller/action/subaction/id would call action_subaction(id) /controller/action/subaction/id 会调用 action_subaction(id)

Is that possible directly from the routemap?可以直接从路线图吗?

Custom action method selector class自定义动作方法选择器 class

If I were you I'd write an action method selector and use that to avoid branching in your actions.如果我是你,我会编写一个动作方法选择器并使用它来避免你的动作分支。 I've written one that separates actions that take optional parameters (thus avoiding branched code within action - simplified unit testing).我写了一个分离带有可选参数的动作(从而避免动作中的分支代码 - 简化的单元测试)。 Default Asp.net MVC defined route has an optional id parameter默认 Asp.net MVC 定义的路由有一个可选的id参数

{controller}/{action}/{id}
id = UrlParameter.Optional

So it makes sense to have these two action methods:所以有这两种操作方法是有意义的:

public ActionResult Index() { ... }
public ActionResult Index(int id) { ... }

I've accomplished just that by writing a custom action selector filter.我通过编写自定义操作选择器过滤器来实现这一点。 Here's a detailed blog post that describes the whole thing and provides some code you can peek at.这是一篇详细的博客文章,描述了整个事情并提供了一些您可以查看的代码。

How about a solution for your problem如何解决您的问题

In your case this means you'd have to write a custom action method selector class called SubactionAttribute and then simply decorate your actions with it:在您的情况下,这意味着您必须编写一个名为SubactionAttribute的自定义操作方法选择器 class ,然后简单地用它装饰您的操作:

[Subaction("Details")]
public ActionResult Members(long id)
{
    var member = _payment.GetMember(id);
    return View("Members.Details", member);
}

[Subaction] // no name would mean default subaction (when not provided)
public ActionResult Members()
{
    var members = _payment.GetMembers().ToList();
    return View("Members.List", members);
}

I'm not going to write the whole class for you, but I will only point you in the right direction so you can follow the same path to get where you're headed:我不会为您编写整个 class,但我只会为您指明正确的方向,以便您可以按照相同的路径到达您的目标:

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true, Inherited = true)]
public sealed class SubactionAttribute : ActionMethodSelectorAttribute
{
    #region Properties

    /// <summary>
    /// Gets subaction name.
    /// </summary>
    public string Name { get; private set; }

    #endregion

    #region Constructors

    /// <summary>
    /// Initializes a new instance of the <see cref="SubactionAttribute"/> class.
    /// </summary>
    public SubactionAttribute()
        : this(null)
    {
        // does nothing
    }

    /// <summary>
    /// Initializes a new instance of the <see cref="SubactionAttribute"/> class.
    /// </summary>
    /// <param name="subactionName">Sub-action name</param>
    public SubactionAttribute(string subactionName)
    {
        this.Name = subactionName;
    }

    #endregion

    #region ActionMethodSelectorAttribute implementation

    /// <summary>
    /// Determines whether the action method selection is valid for the specified controller context.
    /// </summary>
    /// <param name="controllerContext">The controller context.</param>
    /// <param name="methodInfo">Information about the action method.</param>
    /// <returns>
    /// true if the action method selection is valid for the specified controller context; otherwise, false.
    /// </returns>
    public override bool IsValidForRequest(ControllerContext controllerContext, MethodInfo methodInfo)
    {
        if (controllerContext == null)
        {
            throw new ArgumentNullException("controllerContext");
        }

        // get the value of subaction here
        string subName = /* this part you'll have to write */

        // determine whether subaction matches
        return this.Name == subName;
    }

    #endregion
}

Are you saying you effectively want to use multiple "Details" actions in the same controller?您是说您实际上想在同一个 controller 中使用多个“详细信息”操作吗? If this is the case then I think this is a good reason to start splitting your controllers.如果是这种情况,那么我认为这是开始拆分控制器的一个很好的理由。

You should probably start with a Controller called Members with Actions Details and List (or Index)您可能应该从称为具有操作详细信息和列表(或索引)的成员的 Controller 开始

/Members/Details/ID
/Members/List/

Do you have a good logical reason to have them all in the same controller?您是否有充分的合乎逻辑的理由将它们全部放在同一个 controller 中?

Alternatively, you could called you Actions MemberDetails and MemberList and URL like...或者,您可以称您为 Actions MemberDetails 和 MemberList 和 URL 之类的......

/Controller/MemberDetails/ID
/Controller/MemberList/

Give it a go code:给它一个 go 代码:

[ActionName("Member/Details")]
public ActionResult Members_Details(int id){
    return View();
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM