MVC 宁静路由和返回视图

本文关键字:返回 视图 路由 宁静 MVC | 更新日期: 2023-09-27 18:32:49

我的问题与这个MVC Rest和返回视图非常相似,但答案对我不起作用。我已经使用(http://restfulrouting.com/(在我的MVC应用程序中实现了Restful Routing 。

当我想添加新记录时,url 是:

localhost/operations/1/exhibits/new

这将调用 New 操作,该操作返回 New.cshtml 作为包含表单的视图。当用户提交表单并在 Exhibits 控制器上成功调用"创建"操作时。

如果模型状态有错误,我想返回到新视图,使用输入的日期仍然存在,并显示错误消息(尚未实现(。

现在

return View("New", model)

发回数据并呈现"新建"视图,但 url 更改为:

/localhost/operations/1/exhibits

我已经检查了路由值,返回的操作仍然是"创建"。我有由操作和控制器值驱动的导航链接,不正确的 url 意味着这些链接无法正确呈现。

控制器

public class ExhibitController : Controller
{
    public ActionResult Index()
    {
        CreateExhibitViewModel model = new CreateExhibitViewModel();
        return View(model);
    }
    public ActionResult New()
    {
        return View();
    }
    [HttpPost]
    public ActionResult Create(MyModel model)
    {
        if(!ModelState.IsValid)
        {
            return View("New", model")   
        }
        // Process my model
        return RedirectToAction("Index");
    }
}

视图

@model RocketBook.Web.ViewModels.Exhibit.CreateExhibitViewModel
@{
    Html.HttpMethodOverride(HttpVerbs.Put);
    ViewBag.Title = "Operation " + ViewBag.OperationName;
}
<div class="panel panel-default">
    <div class="panel-heading">
        <h4>New Exhibit</h4>
    </div>
    <div class="panel-body">
        <div class="col-lg-6 form-horizontal">
            @using (var form = Html.Bootstrap().Begin(new Form("create", "exhibit").Id("newexhibit").Type(FormType.Horizontal).FormMethod(FormMethod.Post).WidthLg(4)))
            {
                @Html.AntiForgeryToken()                  
                <fieldset>
                    <legend>Details</legend>
                    @Html.HiddenFor(m => m.OperationID)
                    @Html.HiddenFor(m => m.JobID)
                    @form.FormGroup().TextBoxFor(m => m.Barcode)
                    @form.FormGroup().TextBoxFor(m => m.ExhibitRef)
                    @form.FormGroup().TextBoxFor(m => m.ExhibitDescription)
                    @form.FormGroup().DropDownListFor(m => m.ClassificationGroupID, Model.ClassificationGroups).OptionLabel("")
                    @form.FormGroup().DropDownListFor(m => m.ClassificationID, Model.Classifications).OptionLabel("")
                    @form.FormGroup().DropDownListFor(m => m.ExhibitPriority, Model.EntityPriorities).OptionLabel("")
                </fieldset> 
                <hr />
                @(form.FormGroup().CustomControls(
                Html.Bootstrap().SubmitButton().Style(ButtonStyle.Primary).Text("Add Exhibit")))
            }
        </div>
    </div>
</div>

MVC 宁静路由和返回视图

我在 RestfulRouting Github 页面上继续讨论

https://github.com/stevehodgkiss/restful-routing/issues/76

对于任何也发现这种行为并感到困惑的人来说,不要这样,这实际上是正确的行为。这是Steve Hodgkiss为 ASP.NET MVC创建RestfulRouting 项目的解释

不,这是您在创建模型时要走的路径,如果出现问题,很自然地会在那里停止。当他们通过验证时,他们可以继续前进...

存在几种用于区分 URL 的解决方案。调用时使用的 HTTP 方法

http://localhost/operations/1/exhibits

是一个 GET 请求,应调用索引操作。如果我们在创建操作中出现错误返回到此 URL,则 HTTP 方法应显示为 POST。这可以使用

System.Web.HttpContext.Current.Request.HttpMethod

哈立德建议的另一种解决方案是:

如果您使用的是视图模型,则可以从操作内部翻转视图模型上的值。由于您要在"创建"操作中返回模型,因此只需触摸属性即可。可能会让你免于拥有

System.Web.HttpContext.Current.Request.HttpMethod 在你的代码中徘徊。

哦,如果你把它放在视图模型上,你可以用ActionFilter创建一个约定。如果模型 == FlippyModel,只需自动翻转该属性即可。如果失败,则该属性将为 true,如果它通过,您将转到下一个视图。

乍一看,OperationsId 似乎没有解析为 url/form 操作。

当您第一次进入"新建"页面时,发生的情况是 operationId 由 ASP.NET MVC 传入。 ASP.NET MVC 通过尝试查找和使用任何路由值并将其插入路由来提供帮助。听起来令人困惑,但让我通过网址解释一下。

// url
/localhost/operations/1/exhibits/new
// on the view
Url.Action("create", "exhibits", new { /* operationId is implicit */ })

接下来,我们对创建操作执行 POST 操作。

// url 
/localhost/operations/1/exhibits
// on the view
Url.Action("create", "exhibits", new { /* operationId is missing! */ })

当您被发送回此页面时,会出现此问题,因为上面的操作缺少 operationId。这是 MVC 中路由值字典 ASP.NET 症状(我不知道它为什么这样做,但它确实如此(。

溶液:

我使我所有的路由都显式,不要依赖 MVC ASP.NET 给你隐值,因为很难记住何时使用它们。相反,只要养成总是明确表达的习惯。

// on new the view
Url.Action("create", "exhibits", new { operationId = Model.OperationId })
// on the edit view
Url.Action("update", "exhibits", new { operationId = Model.OperationId, id = Model.Id })

这每次都有效,您不必担心所需的值是否位于路由值字典中。