Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/335.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/asp.net-mvc/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在asp.net mvc控制器操作中验证失败时,如何保留url_C#_Asp.net Mvc - Fatal编程技术网

C# 在asp.net mvc控制器操作中验证失败时,如何保留url

C# 在asp.net mvc控制器操作中验证失败时,如何保留url,c#,asp.net-mvc,C#,Asp.net Mvc,如果我从详细信息页面开始: http:\\www.mysite.com\App\Detail 我有一个名为更新的控制器操作,通常会调用重定向到操作返回到详细信息页面。但我有一个在验证中捕获的错误,我需要在重定向之前返回(以避免丢失所有ModelState)。这是我的控制器代码: public override ActionResult Update(Application entity) { base.Update(entity); if (!Mode

如果我从详细信息页面开始:

http:\\www.mysite.com\App\Detail
我有一个名为更新的控制器操作,通常会调用重定向到操作返回到详细信息页面。但我有一个在验证中捕获的错误,我需要在重定向之前返回(以避免丢失所有ModelState)。这是我的控制器代码:

 public override ActionResult Update(Application entity)
    {
        base.Update(entity);
        if (!ModelState.IsValid)
        {
            return View("Detail", GetAppViewModel(entity.Id));
        }
      return RedirectToAction("Detail", new { id = entity.Id }) 
但是现在我看到了带有验证错误消息的视图(因为我使用的是HTML.ValidationSummary()),但url如下所示:

http:\\www.mysite.com\App\Update

不管怎样,我是否可以避免URL更改,而不用将modelstate放入一些临时变量?这里是否有最佳实践,因为我所看到的唯一示例是在调用重定向到操作之间的tempdata中放入ModelState,您要求的最佳实践实际上是您解释不允许的:将ModelState放入tempdata。Tempdata就是为它设计的,这就是为什么我不会称它为黑客


如果这是一段重复性很强的代码,那么可以使用MVCContrib的属性modeldatatotempdata。但是存储仍然是TempData。

从ASP.NET MVC 2开始,当从另一个操作方法调用
return View()
时,没有任何这样的API调用来维护原始操作方法的URL

因此,在ASP.NET MVC中,推荐的解决方案和公认的约定是使用相应的、名称类似的操作方法,该方法只接受
HTTPPOST
动词。因此,在您的情况下,使用另一个名为
Detail
的类似操作方法可以解决验证失败时使用不同URL的问题

[HttpPost]
public ActionResult Detail(Application entity)
{
    base.Update(entity);
    if (ModelState.IsValid)
    {
        //Save the entity here
    }
   return View("Detail", new { id = entity.Id });
}  

此解决方案符合ASP.NET MVC最佳实践,还避免了在moderatetempdate上乱动

此外,如果您还没有研究过此选项,那么asp.net mvc中的客户端验证也可能为您的URL问题提供一些解决方案。我强调一些
,因为当浏览器上禁用javascript时,这种方法不起作用


因此,最好的解决方案是使用名为
Detail
的操作方法,但只接受
httppost
动词。

这里的问题实际上是由您的实现引起的。这并不能回答你的问题,但它描述了你一开始犯的错误

如果您想要一个用于更新或编辑项目的页面,URL应该反映这一点。比如说

您可以访问http:\www.mysite.com\App\Detail,它会显示一些信息。这就是URL描述的它将要做的事情。在控制器中,Detail()方法将返回Detail.aspx视图

要编辑项目,请访问http:\www.mysite.com\App\edit并更改要更新的信息,表单将发回同一URL-您可以使用以下方法在控制器中处理此问题:

[HttpGet]
public ActionResult Edit() {
    MyModel model = new MyModel();
    ...
    return View(model);
}

[HttpPost]
public ActionResult Edit(MyModel model) {
    ...
    if (ModelState.IsValid) {
        // Save and redirect
        ...
        return RedirectToAction("Detail");
    }
    return View(model);
}
如果你发现自己在做这件事

return View("SomeView", model);
你让自己的生活变得更艰难(同时也打破了URL背后的原则)

如果要重复使用视图的一部分,请将其设置为局部视图,并在以控制器上的方法命名的视图中进行渲染


我很抱歉,这可能没有多大帮助,但通过从不同名称的方法显示相同的视图,您正在落入MVC反模式陷阱。

正如@Malcolm sais所说,最佳做法是将
ModelState
放在
TempData
中,但不要手动执行!如果在每个相关的控制器操作中手动执行此操作,将引入大量重复代码,并大大增加维护成本

相反,实现几个属性来完成这项工作。(向下滚动到帖子末尾)这已经被广泛传播,埃文·纳格尔展示了一个与卡齐基本相同但名字不同的名字。因为他还提供单元测试来确保属性工作,所以在代码中实现它们将意味着很少或没有维护成本。唯一需要注意的是,控制器操作使用适当的属性进行修饰,这些属性也可以进行测试

当属性就绪时,控制器可能看起来像这样(我特意简化了,因为我不知道从哪个类继承):

您提到您觉得将
ModelState
放在
TempData
中感觉像是“黑客”——为什么?我同意你的观点,在每一个控制器动作中使用重复的代码似乎有点骇人,但这不是我们现在要做的。事实上我不认为上面的代码看起来有问题。。。你知道吗


虽然有一些解决这个问题的方法看起来更简单,比如重命名action方法以保留URL,但我强烈建议不要使用这种方法。它确实解决了这个问题,但还引入了一些其他问题-例如,您仍然无法防止双重表单提交,并且您的操作名称非常混乱(调用
详细信息
实际上会更改服务器上的内容)。

@Bikal Gurung-谢谢。我一直认为这是一种奇怪的做法,因为操作的名称并不真正代表您正在做的事情,但我确实同意,这将解决我所问的问题您可以使用[ActionName(“细节”)]public ActionResult WhatEverMethodName()解决这个问题,现在该方法将对应于“/Details”“此解决方案符合ASP.NET MVC最佳实践…”-我认为它实际上不符合最佳实践。从POST调用返回视图与PRG模式直接冲突,PRG模式是整个web的最佳实践,而不仅仅是ASP.NET MVC。遵守PRG的方法很多
[HttpPost, PassState]
public ActionResult Update(EntityType entity)
{
    // Only update if the model is valid
    if (ModelState.IsValid) {
        base.Update(entity);
    }
    // Always redirect to Detail view.
    // Any errors will be passed along automagically, thanks to the attribute.
    return RedirectToAction("Detail", new { id = entity.Id });
}

[HttpGet, GetState]
public ActionResult Detail(int id)
{
    // Get stuff from the database and show the view
    // The model state, if there is any, will be imported by the attribute.
}