【问题标题】:Using TempData inside scripts when returning a PartialView返回 PartialView 时在脚本中使用 TempData
【发布时间】:2017-08-07 15:03:31
【问题描述】:

我正在尝试将 TempData 值传递给我的视图,但我的控制器操作是一个 ajax 后控制器并返回一个部分视图。

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(CategoryViewModel model)
{
    if (ModelState.IsValid)
    {
        var category = new Category()
        {
            Name = model.Name,
            Description = model.Description
        };
        //test
        System.Threading.Thread.Sleep(2000);

        try
        {
            _repository.AddCategory(category);

            TempData["success"] = string.Format("Category Added");
            return PartialView("~/Areas/Dashboard/Views/Category/_List.cshtml", CategoryListMap());
        }
        catch(Exception ex)
        {
            TempData["error"] = string.Format("{0}", ex);
            return PartialView("~/Areas/Dashboard/Views/Category/_List.cshtml", CategoryListMap());
        }
    }

    TempData["error"] = string.Format("Modal state is not valid");
    return PartialView("~/Areas/Dashboard/Views/Category/_List.cshtml", CategoryListMap());
}

我对创建表单的部分看法:

@using (Ajax.BeginForm("Create", "Category", new { area = "dashboard" }, new AjaxOptions { UpdateTargetId = "categories", OnComplete = "onComplete", OnBegin = "onBegin" }))
{
    @Html.AntiForgeryToken()
    <div class="modal-body">
        <div class="form-group">
            @Html.LabelFor(m => m.Name)
            @Html.TextBoxFor(m => m.Name, new { @class = "form-control" })
            @Html.ValidationMessageFor(m => m.Name)
        </div>
        <div class="form-group">
            @Html.LabelFor(m => m.Description)
            @Html.TextAreaFor(m => m.Description, new { @class = "form-control", rows = "5" })
            @Html.ValidationMessageFor(m => m.Description)
        </div>
    </div>
    <div class="modal-footer">
        <button type="button" class="btn btn-white" data-dismiss="modal">Close</button>
        <button class="ladda-button btn btn-primary" type="submit" data-style="zoom-in">Add</button>
    </div>
}

所以我的控制器由于ajax形式必须返回一个partialview,并且值TempData被传递给_list partialview

@if (TempData["error"] != null)
{
    <p>
        <div class="alert alert-danger alert-dismissable">
            <button aria-hidden="true" data-dismiss="alert" class="close" type="button">×</button>
            @TempData["error"]
        </div>
    </p>
}
@if (TempData["success"] != null)
{
    <p>
        <div class="alert alert-success alert-dismissable">
            <button aria-hidden="true" data-dismiss="alert" class="close" type="button">×</button>
            @TempData["success"]
        </div>
    </p>
}

<table class="table table-striped table-bordered table-hover dataTables">
    <thead>
        <tr>
            <th>#</th>
            <th>Name</th>
            <th>Description</th>
        </tr>
    </thead>
    <tbody>
        @foreach (var category in Model)
        {
            <tr>
                <td>
                    @Html.DisplayFor(m => category.CategoryId)
                </td>
                <td>
                    @Html.DisplayFor(m => category.Name)
                </td>
                <td>
                    @Html.DisplayFor(m => category.Description)
                </td>
            </tr>
        }
    </tbody>
    <tfoot>
        <tr>
            <th>#</th>
            <th>Name</th>
            <th>Description</th>
        </tr>
    </tfoot>
</table>

如您所见,我在局部视图中获取了 TempData 值,一切正常,但我遇到的问题是如何在视图中获取 TempData 值?试图在视图本身中获取 TempData 值,但它不起作用,因为我认为在我的控制器中我正在返回一个局部视图,并且 TempData 值只会在请求局部视图时显示?

这是我的完整观点:

<div class="row wrapper border-bottom white-bg page-heading">
    <div class="col-lg-10">
        <h2>Categories</h2>
        <ol class="breadcrumb">
            <li>
                <a href="@Url.Action("Index", "Category")">Categories</a>
            </li>
            <li class="active">
                <strong>List</strong>
            </li>
        </ol>
    </div>
    <div class="col-lg-2">
    </div>
</div>
<div class="wrapper wrapper-content animated fadeInRight">
    <div class="row">
        <div class="col-lg-12">
            <div class="ibox float-e-margins">
                <div class="ibox-title">
                    <button type="button" class="btn btn-primary" data-toggle="modal" data-target="#myModal1">
                        <i class="fa fa-plus"></i>
                    </button>
                </div>

                <div class="ibox-content table-responsive">
                    <div id="categories">
                        @{Html.RenderAction("List", "Category", new { area = "dashboard" });}
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>

<div class="modal inmodal" id="myModal1" tabindex="-1" role="dialog" aria-hidden="true" data-backdrop="static">
    <div class="modal-dialog">
        <div class="modal-content animated fadeIn">
            <div class="modal-header">
                <button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">&times;</span><span class="sr-only">Close</span></button>
                <h4 class="modal-title">Add a category</h4>
            </div>
            @{ Html.RenderAction("Create", "Category", new { area = "dashboard" });}
        </div>
    </div>
</div>

@section Scripts {
    @Scripts.Render...blahblah

    <script type="text/javascript">

        function onSuccess() {
            //remove toastr
            toastr.remove();
            **//not working, tempdata value not set**
            toastr.success('@TempData["success"]', 'Success');
        }

        function onFailure() {
            //remove toastr
            toastr.remove();
            **//not working, tempdata value not set**
            toastr.error('@TempData["error"]', 'Error');
        }
    </script>
}

如果我尝试在完整视图中使用 TempData 值,则没有设置任何值...我无法在局部视图中呈现脚本,据我了解,您也不应该在局部视图中编写任何脚本,那么当我返回带有 tempdata 的局部视图时,如何在脚本中使用 tempdata 值???

【问题讨论】:

  • 首先TempData 不合适,应该是ViewBag。您始终可以在带有值的部分中生成隐藏输入,然后在 ajax 成功回调中访问它并更新主视图。
  • @Stephen Muecke 更新主视图?但是,ajax 的全部处理不就是您只更新部分视图吗?如果您的意思只是将 TempData 更改为 ViewBag,它仍然给我同样的问题,在主视图中访问 ViewBag 时没有任何价值
  • 我的意思是更新你需要的东西。但真正的问题是你的方法是错误的。您只需要返回一个 JsonResult 来指示成功或其他情况,如果成功,则通过根据表单值在表中添加新行来更新 DOM。不需要更新整个表
  • 我假设您没有理解我的第一条评论。在您的部分添加 &lt;input type="hidden" id="message" value="@ViewBag.Message" /&gt; 然后在回调中,您可以使用 var message=$('#message").val(); 获取它并使用它做任何您想做的事情。
  • 请参阅this DotNetFiddle 了解您可以做什么的示例。

标签: javascript asp.net ajax asp.net-mvc partial-views


【解决方案1】:

您使用 TempData 不合适(用于在控制器方法之间传递数据),并且对于将数据从控制器传递到视图,您应该使用 ViewBagViewData(或者更好的是,视图模型中的属性)。

但问题是您进行了一个 ajax 调用,该调用接收您的控制器创建的部分视图的 html。您没有将 TempData["error"]TempData["success"] 的值发送回客户端,只是将部分视图的 html 发送回。

您可以通过将您的消息添加到 ViewBag 属性来做到这一点

ViewBag.Message = "...."; // your success or error message

在局部视图中,创建一个隐藏的输入来存储值

<input type="hidden" id="message" value="@ViewBag.Message" />

在ajax成功回调中,你可以使用

success: function(data) {
    $('someElement').append(data); // append the partial view to the DOM
    var message = $('#message').val(); // get the value of the message
    toastr.success(message , 'Success'); // display it
}

但是,返回整个表的一部分并在视图中替换它不是很有效,您应该考虑进行 ajax 调用以保存数据,然后返回 json 以指示成功或其他情况,然后只是附加一个新表ros 基于表单中的值。以DotNetFiddle 为例。

【讨论】:

  • 如果我想添加row id,是否需要在添加后从数据库中获取id并用json传回?
  • 是的(但是当您在上下文中调用 saveChanges() 时,ID 属性将自动更新,因此您可以使用 int ID = category.CategoryId 访问新 ID 并将其传递回客户端
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-19
  • 1970-01-01
  • 1970-01-01
  • 2012-06-07
  • 1970-01-01
  • 2015-03-11
相关资源
最近更新 更多