简体   繁体   中英

Using TempData inside scripts when returning a PartialView

I am trying to pass TempData value to my view, but my controller action is an ajax post controller and returns a partialview.

[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());
}

My partial view of a create form:

@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>
}

So my controller must returns a partialview because of the ajax form, and the value TempData is passed to the _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>

As you can see I'm getting the TempData value inside my partialview, everything is working fine but the problem I'm having is how do I get the TempData value inisde my view instead? I tried to get the TempData value inside the view itself but its not working because I think in my controller I'm returning a partialview and the TempData value will only display when a partialview is been requested?

Here is my full view:

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

If I try to use TempData value inside the full view, no value is set...I can't render Scripts inside a partialview and from my understanding you shouldn't write any scripts inside a partialview as well, so how can I use the tempdata value inside the script when I'm returning a partial view with tempdata???

You use of TempData is not appropriate (which is for passing data between controller methods), and for passing data from a controller to a view, you should be using ViewBag or ViewData (or better still, a property in a view model).

But the issue is that your making an ajax call which receives the html of the partial view your controller creates. Your not sending the value of TempData["error"] or TempData["success"] back to the client, just the html of your partial view.

You could do this by adding your message to a ViewBag property

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

and in the partial view, create a hidden input to store the value

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

and the in the ajax success calback, you can access it using

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
}

However, returning a partial of the whole table and replacing it in the view is not very efficient and you should consider making your ajax call to save the data and then returning json to indicate success or otherwise and then just appending a new table ros based on the values in your form. Refer this DotNetFiddle for an example.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM