MVC Restful路由和返回视图

时间:2013-09-25 13:48:25

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

我的问题非常类似于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)

发回数据并呈现“新”视图,但网址更改为:

/localhost/operations/1/exhibits

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

控制器

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>

2 个答案:

答案 0 :(得分:1)

我继续讨论

上的RestfulRouting Github页面

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

对于那些也发现这种行为并且感到困惑的人,不要这样做,这实际上是正确的行为。以下是Steve Hodgkiss对ASP.NET MVC的RestfulRouting项目的创建者的解释

  

不,这是预期的,这是你在创建模型时所走的路径,如果出现问题,它在那里停止是很自然的。当他们通过验证时,他们可以继续......

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

时使用的HTTP方法
http://localhost/operations/1/exhibits

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

访问
System.Web.HttpContext.Current.Request.HttpMethod

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

  

如果您使用的是ViewModel,则只需在操作内部翻转ViewModel上的值即可。由于您在“创建”操作中返回模型,因此您只需触摸属性即可。可能会让你免于

     

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

     

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

答案 1 :(得分:0)

乍一看,看起来OperationsId没有被解析为url / form动作。

首次进入“新建”页面时会发生的情况是ASP.NET MVC正在传入 operationId 。通过尝试查找和使用任何路由值并将它们插入到您的路由中,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 。这是ASP.NET MVC中路由值字典的一个症状(我不知道为什么会这样做,但确实如此)。

解决方案:

我将所有路由都显式化,不要依靠ASP.NET MVC来提供隐式值,因为要记住何时使用它们太难了。相反,只要养成一直明确的习惯。

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

每次都可以使用,您不必担心所需的值是否位于路线值字典中。