从子动作

时间:2017-10-06 03:28:39

标签: c# asp.net-mvc

我有以下情况:

  • 用户可以对订单发表评论
  • 要显示评论表单,我在订单的@{Html.RenderAction("CreateComment", "Order", new { orderId = Model.Id, orgId = Model.OrganisationId });}视图中调用Details
  • 用户发表评论后,我需要重定向回订单的Details视图
  • 然而,在致电RedirectToAction时,我得到:

      

    不允许子操作执行重定向操作。

要解决此问题,我尝试调用此Redirect

的内容
return View("Details", new { id = viewModel.OrderId });

但现在我看到了这个奇怪的错误:

  

传递到字典中的模型项的类型为'<> f__AnonymousType4`1 [System.Int32]',但此字典需要“ViewOrderViewModel”类型的模型项。

这似乎是抱怨我没有将ViewModel传递给视图。

但是,如果你查看我调用的Details控制器操作,它实际上接受一个int并在那里构建ViewModel(我可以看到在执行上述操作后仍然会触发此操作变化):

public ActionResult Details(int id)
{
    var orderViewModel = orderManager.Select(id);
    return View(orderViewModel);
}

这里发生了什么?为什么我不能像通常那样使用id路由值来调用操作?我的ViewOrderViewModel发生了什么?

非常感谢任何建议。谢谢。

更新以添加代码

订单Details.cshtml

这是我拒绝comments表单的地方,以及我需要在所有这些结束时重定向到的地方。该网址看起来像~/order/details/14

错误似乎出现在@{Html.RenderAction("CreateComment", "Order", new { orderId = Model.Id, orgId = Model.OrganisationId });}行上:

  

不允许子操作执行重定向操作。

@using Web.Resources.Headers

@model Web.Models.ViewOrderViewModel

<div class="container">
    <h4>@Model.Name</h4>
    <hr />
    <div class="col-xs-12">

        <h4>Comments</h4>
        <hr />

        <div class="col-xs-12 col-sm-6">
            @foreach (var comment in Model.Comments)
            {
                @comment.Content
            }
        </div>

        <div class="col-xs-12 col-sm-6">
            @{Html.RenderAction("CreateComment", "Order", new { orderId = Model.Id, orgId = Model.OrganisationId });}
        </div>
    </div>
</div>

CreateComment.cshtml

发表评论的表格

@using Microsoft.AspNet.Identity

@model Web.Models.NewCommentViewModel

@using (Html.BeginForm()) 
{
    @Html.AntiForgeryToken()

    <div class="form-horizontal">
        @Html.ValidationSummary(true, "", new { @class = "text-danger" })

        @Html.HiddenFor(model => model.OrderId)
        @Html.HiddenFor(model => model.OrganisationId)
        @Html.HiddenFor(model => model.UserId)

        <div class="form-group has-feedback">
            <div class="col-xs-12" style="padding:0px;">
                @Html.TextAreaFor(model => model.Content, new { @class = "form-control", placeholder = Html.DisplayNameFor(model => model.Content) })
                <span class="glyphicon glyphicon-option-horizontal form-control-feedback"></span>
            </div>
        </div>

        <div class="form-group">
            <div class="pull-right">
                <input type="submit" value="Create" class="btn btn-default" />
            </div>
        </div>
    </div>
}

OrderController

在这里,您可以看到用于显示评论表单并将评论发布到数据库的控制器方法(“重定向”方法失败,并显示与子操作相同的错误):

public ActionResult CreateComment(int orderId, int orgId)
{
    var viewModel = new NewCommentViewModel()
    {
        OrderId = orderId,
        OrganisationId = orgId,
        UserId = User.Identity.GetUserId()
    };
    return PartialView(viewModel);
}

[HttpPost]
public ActionResult CreateComment(NewCommentViewModel viewModel)
{
    orderManager.AddComment(viewModel);
    return RedirectToAction("Details", new { id = viewModel.OrderId });
    //return Redirect($"/Order/Details/{viewModel.OrderId}");
}

3 个答案:

答案 0 :(得分:1)

@{Html.RenderAction("CreateComment", ...);}可能会调用你的超载。

尝试重命名:

public PartialViewResult _CreateComment(int orderId, int orgId)
{
    var viewModel = new NewCommentViewModel()
    {
        OrderId = orderId,
        OrganisationId = orgId,
        UserId = User.Identity.GetUserId()
    };
    return PartialView(viewModel);
}

并致电:

@{Html.RenderAction("_CreateComment", ...);}

答案 1 :(得分:1)

首先,尝试在部分视图表单中设置BeginForm以包含控制器&amp;动作方法名称使用POST HTTP方法,如下所示:

@using (Html.BeginForm("CreateComment", "Order", FormMethod.Post))
{
    // view controls
} 

同时尝试使用与POST操作方法名称不同的名称分配GET操作方法,并包括ChildActionOnlyAttribute,如下所示:

[ChildActionOnly]
public ActionResult RenderCreateComment(int orderId, int orgId)
{
    var viewModel = new NewCommentViewModel()
    {
        OrderId = orderId,
        OrganisationId = orgId,
        UserId = User.Identity.GetUserId()
    };
    return PartialView(viewModel);
}

然后在RenderAction中分配重命名的操作:

@{Html.RenderAction("RenderCreateComment", "Order", new { ... });}

请注意,子操作应该填充或获取数据,它不应该尝试更新其他内容。

类似问题:

Child actions are not allowed to perform redirect actions

Child actions are not allowed to perform redirect actions MVC4

答案 2 :(得分:1)

问题是您的表单是作为子动作的部分生成的,您是否检查html中的<form>元素,您将看到它生成action="/order/details/14",而它必须是{{} 1}}

您需要更改action="/order/CreateComment"方法以生成正确的属性,以便POST到正确的方法。在BeginForm()视图中

CreateComment.cshtml