【问题标题】:MVC Restful routing and returning ViewsMVC Restful 路由和返回 Views
【发布时间】:2013-09-25 13:48:25
【问题描述】:

我的问题与MVC Rest and returning views 非常相似,但答案对我不起作用。我已经使用 (http://restfulrouting.com/) 在我的 MVC 应用程序中实现了 Restful Routing。

当我想添加一条新记录时,网址是:

localhost/operations/1/exhibits/new

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

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

目前

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>

【问题讨论】:

    标签: c# asp.net-mvc rest razor asp.net-mvc-routing


    【解决方案1】:

    我在

    的 RestfulRouting Github 页面上继续讨论

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

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

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

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

    http://localhost/operations/1/exhibits
    

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

    System.Web.HttpContext.Current.Request.HttpMethod
    

    Khalid 建议的另一个解决方案是:

    如果您使用的是 ViewModel,您可以从动作内部翻转 ViewModel 上的值。由于您在 Create 操作中返回模型,因此您只需触摸一个属性。可能会让你免于拥有

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

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

    【讨论】:

      【解决方案2】:

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

      当您第一次来到新页面时,会发生 operationId 正在由 ASP.NET MVC 传入。 ASP.NET MVC 通过尝试查找和使用任何 old 路由值并将它们插入到您的路由中来提供帮助。听起来令人困惑,但让我通过 url 解释一下。

      // 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。这是 ASP.NET MVC 中路由值字典的症状(我不知道为什么会这样,但确实如此)。

      解决方案:

      我将所有路由都设为显式,不要依赖 ASP.NET MVC 为您提供 implicit 值,因为很难记住何时使用它们。而是养成始终明确的习惯。

      // 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 })
      

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

      【讨论】:

      • 好的,我将 Url.Action 连接到一个链接中,然后使用 Javascript 发回。我仍然得到与我原来的问题完全相同的行为。还有什么想法吗?
      • 啊我明白你现在的意思了,这是 Restful Routing 的预期行为。您不能指望它会转到 /new,因为状态在 post 操作处已停止。 Rails 做同样的事情。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-12
      • 2020-02-01
      • 2018-06-17
      • 2014-10-17
      • 1970-01-01
      相关资源
      最近更新 更多