0

在我的 ASP.NET MVC 应用程序中,我试图实现以下概念:

  • 浏览http://.../PersonData/Show?id=A5668A31-9AAC-4A14-B471-7C9BA236961D应显示由给定 ID 标识的人员的数据。
  • 浏览http://.../PersonData/Show应该显示一个带有表单的视图,我可以在其中将 ID 输入到文本框中。当我提交表单时,浏览器应该导航而不是发布到上面给出的 URL(即,表单的方法设置为 GET)。
  • 当我在不输入 ID 的情况下提交表单(导致 URLhttp://.../PersonData/Show?id=被浏览)时,ASP.NET MVC 模型验证应该显示一条消息,指出需要 ID。(启用或不启用 JavaScript。)

为了实现这一点,我建立了一个这样的模型:

class Model
{
  [Required]
  public Guid? Id { get; set; }
}

现在我有一个问题,当第一次浏览http://.../PersonData/Show时,ASP.NET 模型验证立即给出了一个需要 ID 的错误,因为它不区分没有 ID ( ?id=) 提交表单的情况和提交的情况第一次调用该操作(根本没有给出 id)。

我有过的想法:

  • 使用两个不同的控制器操作和 URL(如http://.../PersonData/Searchhttp://.../PersonData/Show?id=)来区分首次浏览和空表单提交。
  • 使用额外的表单参数(如http://.../PersonData/Showand http://.../PersonData/Show?valueGiven=true&id=)。
  • 使用该Request对象检查操作方法中的 URL 参数,并清除该键是否存在于 URL 中的ModelState错误。"id"

解决此问题的最佳/建议方法是什么?有没有更好的第四种方法?

(一件事不起作用是为 GET 操作添加两个具有相同名称的操作方法:

[HttpGet]
public void Show() { /* return view with initial browsing logic */ }
[HttpGet]
public void Show(Model model) { /* return view with subsequent browsing logic */ }

ASP.NET MVC 似乎不允许这样做。)

2013-06-25 更新:对不起,我的示例中有两个错误,ID 应该是一个Guid,而不是一个字符串;当然,我将模型绑定到我的操作方法中,因为我需要Required评估属性。

这是我的路由配置:

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

  routes.MapRoute (
      name: "Default",
      url: "{controller}/{action}",
      defaults: new { controller = "Home", action = "Index" }
  );
}
4

3 回答 3

1

如果您不传递 id,则 id 将为空。如果您通过值传递 id,则 id 将为“”(即,空字符串..String.Empty)

因此,您不能使用Required 属性,因为这会产生错误。您必须在控制器中手动检查该值。

更好的方法是创建一个特殊的路由来处理带有 id 的版本,使用路由约束。此路由中的 id 不是可选的,但约束会阻止根本没有 id 的路由不被选择。

我现在没有能力为你创建和测试这个案例,但这应该会给你一些东西。也许其他人可以掀起一些东西。

可以在此处找到有关路线约束的信息:

http://www.asp.net/mvc/tutorials/controllers-and-routing/creating-a-route-constraint-cs

于 2013-06-24T15:51:23.363 回答
1

如果我要将这两种方法都用作 GET,那么我更喜欢您的第一种方法:一个搜索页面和一个传入参数的结果页面。如果我希望用户共享链接,这是我喜欢采用的方法,因为所有参数将在查询字符串中。

另一方面,如果共享不是真正的问题,我希望有一个 GET 方法来显示表单,然后将其提交给具有相同名称的 action 方法的 POST 版本。

于 2013-06-24T15:51:41.247 回答
0

只需在您的初始显示功能中添加一个 if 案例

[HttpGet]
public void Show(int? id) {

    if(id.HasValue) {
     /* return view with subsequent browsing logic */ 
    }
    else {
      /* return view with initial browsing logic */
    }
}

编辑:这可能有效

    [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
    public class RequestMatchAnyAttribute : ActionNameSelectorAttribute
    {
        public string MatchFormKey { get; set; }

        public RequestMatchAnyAttribute(string matchAnyFormKeys)
        {
            this.MatchFormKey = matchAnyFormKeys;
        }

        public override bool IsValidName(ControllerContext controllerContext, string actionName, MethodInfo methodInfo)
        {
            return controllerContext.HttpContext.Request[MatchFormKey] != null;
        }
    }


[HttpGet]
public void Show() {
    /* default view */
}

[ActionName("Show")]
[RequestMatchAny("Id")]
[HttpGet]
public void ShowEdit(int? id) {

    if(id.HasValue) {
     /* return edit view */ 
    }
    else {
      /* return create view */
    }
}
于 2013-06-24T16:58:46.240 回答