Asp.net mvc 如何区分ASP.NET MVC 4控制器中的空模型和初始模型?
在我的ASP.NET MVC应用程序中,我尝试实现以下概念:Asp.net mvc 如何区分ASP.NET MVC 4控制器中的空模型和初始模型?,asp.net-mvc,asp.net-mvc-4,get,data-annotations,model-binding,Asp.net Mvc,Asp.net Mvc 4,Get,Data Annotations,Model Binding,在我的ASP.NET MVC应用程序中,我尝试实现以下概念: 浏览http://.../PersonData/Show?id=A5668A31-9AAC-4A14-B471-7C9BA236961D应显示由给定ID标识的人员的数据 浏览http://.../PersonData/Show应该显示一个带有表单的视图,我可以在其中向文本框中输入ID。当我提交表单时,浏览器应该导航到上面给出的URL,而不是post(即表单的方法设置为GET) 当我提交表单时没有输入ID(导致URLhttp://..
- 浏览
http://.../PersonData/Show?id=A5668A31-9AAC-4A14-B471-7C9BA236961D应显示由给定ID标识的人员的数据
- 浏览
应该显示一个带有表单的视图,我可以在其中向文本框中输入ID。当我提交表单时,浏览器应该导航到上面给出的URL,而不是post(即表单的方法设置为GET)http://.../PersonData/Show
- 当我提交表单时没有输入ID(导致URL
待浏览),ASP.NET MVC模型验证应显示需要ID的消息。(启用或不启用JavaScript。)http://.../PersonData/Show?id=
class Model
{
[Required]
public Guid? Id { get; set; }
}
现在我有一个问题,当浏览http://.../PersonData/Show
ASP.NET模型验证第一次立即给出一个错误,即ID是必需的,因为它不区分提交表单时没有ID的情况(?ID=
)以及第一次调用操作的情况(完全没有给出id)
我的想法是:
- 使用两种不同的控制器操作和URL(如
和http://.../PersonData/Search
)以区分首次浏览和空表单提交http://.../PersonData/Show?id=
- 使用附加的表单参数(如
和http://.../PersonData/Show
)http://.../PersonData/Show?valueGiven=true&id=
- 使用
对象检查操作方法中的URL参数,如果URL中不存在该键,则清除请求
错误模型状态
[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
,而不是字符串;当然,我在action方法中绑定模型是因为我需要计算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" }
);
}
若您不传递id,那个么id将为空。如果用值传递id,id将为“”(即,空字符串..string.empty) 因此,您不能使用Required属性,因为这将生成一个错误。您必须手动检查控制器中的值 更好的方法是创建一个特殊的路由,使用路由约束来处理id为的版本。此路由中的id不是可选的,但该约束将阻止根本没有id的路由不被选择 我现在没有能力为您创建和测试这个案例,但这应该会给您一些继续下去的机会。也许其他人可以做点什么 有关路线约束的信息可在此处找到:
如果我将两种方法都作为GET,那么我更喜欢您的第一种方法:搜索页面和带有传入参数的结果页面。如果我想让用户共享链接,我喜欢采用这种方法,因为所有参数都将在querystring中
另一方面,如果共享不是一个真正的问题,我希望有一个GET方法来显示表单,然后将表单提交给具有相同名称的操作方法的后期版本。只需在初始显示函数中添加一个If case即可
[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 */
}
}
你能给我看一下路线配置吗?看起来路由中的ID未设置为可选!这不是我所需要的——我需要区分三种情况:初始浏览、随后使用给定id浏览和随后不使用给定id浏览。(请注意,我原来的问题文本中有两个错误。)@FabianSchmied为什么不对列表使用不同的操作,对create/editSure使用不同的操作,这是我问题的第一个选项:)我只是想看看是否有更好的替代方法。谢谢,你是对的,使用字符串(并省略必需的属性)我可以手动检查。但是,我在原始问题文本中犯了一个错误,实际上有一个
Guid?
——在这种情况下,没有可区分的第三个值(模型绑定器将两个“空”案例绑定到null
)。省略RequiredAttribute
意味着我还必须手动附加客户端验证,因此这很不幸(当然可能)。关于路由约束:id
作为URL参数传递(因为它是一个带有GET方法的HTML表单)。我不能根据一个新的路线创建路线,可以吗?如果是,具体如何?