MVC 3 + $阿贾克斯 - 反应似乎从缓存局部视图输出 [英] MVC 3 + $.ajax - response seems to be caching output from partial view

查看:124
本文介绍了MVC 3 + $阿贾克斯 - 反应似乎从缓存局部视图输出的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我必须失去了一些东西,傻傻的,但这里的问题。

我有交易控制器上创建操作。该Create.cshtml使用jQuery的形式张贴到使用调用$阿贾克斯服务器。调试表明,一切都到达服务器上的预期。我用表单数据更新记录:这也正常工作。然后我返回一个局部视图,传递一个模型来使用默认的数据视图。我可以调试和验证模型是通过空和0,即默认的数据我的模型。

问题是,什么被送回了响应的浏览器是以前的数据!

我看不出有什么理由。希望你可以...

注意:我没有使用任何形式的输出缓存

编辑1:

的缓存未在浏览器中发生的情况。我说的原因是,我可以在Firebug看到调用AjaxCreate行动响应。我也可以看到这一点提琴手。

编辑2:

如果你看一下code的局部视图,你会看到每个DropDownList的或文本框具有@ Model.Transaction的价值。[属性]打印出来,在它旁边。这奇怪的是,显示了正确的值,也就是说,我的交易对象违约,但dropdownlists和文本框坚持与被发送到服务器,而不是对每个人都应该呈现属性的默认值的值。

编辑3:

我已经包括下面的图片,所以你可以看到印到在传递每个控制权的价值。然而,对照反思发布到服务器在previous $阿贾克斯旧数据呼叫。 (注释显示在创建视图模型,这样我能看到的东西更新的时刻的日期时间)。

编辑4:

我发现,替换@ Html.EditorFor(...)(见视图$ C $下面c)与@ Html.TextBox助手删除的问题。那么,是什么似乎是发生的是,EditorFor佣工造成问题的原因。为什么?我不知道,但会发布另一个更具体的问题。

code和标记如下:

jQuery的:

  $(文件)。就绪(函数(){    $(输入[名称=nextRecord]')。生活('点击',功能(){
        VAR theForm = $(本).closest(形式);
        如果((theForm).valid()){
            VAR buttonText = $(本).VAL();
            VAR行动=/输入/交易/ AjaxCreate /;
            如果(buttonText ===复位){
                clearForm(theForm);
            }
            其他{
                VAR targetElement = $('#CreateDiv');
                VAR _data = theForm.serialize()+'&放大器; nextRecord ='​​+ $(本).VAL();                $阿贾克斯({
                    网址:动作,
                    数据:_data,
                    缓存:'假',
                    输入:POST,
                    数据类型:HTML,
                    成功:功能(HTML){
                        $(targetElement)的.html(HTML);
                        createDatePickers(targetElement);
                        jQuery.validator.unobtrusive.parse(targetElement);
                    }
                });
            }
        }
        返回false;
    });
});

局部视图:

  @model FlatAdmin.Domain.ViewModels.TransactionViewModel@ *这个局部视图定义创建和编辑实体时将出现表单字段* @< D​​IV CLASS =编辑标记>
    出生日期
< / DIV>
< D​​IV CLASS =主编场>
    @ Html.EditorFor(型号=> model.Transaction.TransactionDate,新{@class =日期选取器})
    @ Html.ValidationMessageFor(型号=> model.Transaction.TransactionDate)@ Model.Transaction.TransactionDate.ToString()
< / DIV>< D​​IV CLASS =编辑标记>
    俄:
< / DIV>
< D​​IV CLASS =主编场>
    @ Html.DropDownListFor(型号=> model.Transaction.IdFrom,((IEnumerable的< FlatAdmin.Domain.Entities.Account>)Model.FromAccounts)。选择(选项=>新建SelectListItem
{
        文字=(选项== NULL无:option.AccountName)
        值= option.AccountId.ToString(),
        选择=(型号!= NULL)及和放大器; (option.AccountId == Model.Transaction.IdFrom)
    }),选择...)
    @ Html.ValidationMessageFor(型号=> model.Transaction.IdFrom)@ Model.Transaction.IdFrom
< / DIV>< D​​IV CLASS =编辑标记>
    DESTINO:
< / DIV>
< D​​IV CLASS =主编场>
    @ Html.DropDownListFor(型号=> model.Transaction.IdTo,((IEnumerable的< FlatAdmin.Domain.Entities.Account>)Model.ToAccounts)。选择(选项=>新建SelectListItem
{
    文字=(选项== NULL无:option.AccountName)
    值= option.AccountId.ToString(),
    选择=(型号!= NULL)及和放大器; (option.AccountId == Model.Transaction.IdTo)
}),选择...)
    @ Html.ValidationMessageFor(型号=> model.Transaction.IdTo)@ Model.Transaction.IdTo
< / DIV>
< D​​IV CLASS =编辑标记>
    蒙托
< / DIV>
< D​​IV CLASS =主编场>
    @ Html.DropDownListFor(型号=> model.Transaction.IdCurrency,((IEnumerable的< FlatAdmin.Domain.Entities.Currency>)Model.AllCurrencies)。选择(选项=>新建SelectListItem
{
    文字=(选项== NULL无:option.CurrencyName)
    值= option.CurrencyId.ToString(),
    选择=(型号!= NULL)及和放大器; (option.CurrencyId == Model.Transaction.IdCurrency)
}))
    @ Html.EditorFor(型号=> model.Transaction.Amount)
    @ Html.ValidationMessageFor(型号=> model.Transaction.Amount)@ Model.Transaction.Amount
< / DIV>< D​​IV CLASS =编辑标记>
    Comentario
< / DIV>
< D​​IV CLASS =主编场>
    @ Html.EditorFor(型号=> model.Transaction.Comment)
    @ Html.ValidationMessageFor(型号=> model.Transaction.Comment)@ Model.Transaction.Comment
< / DIV>

查看:

  @model FlatAdmin.Domain.ViewModels.TransactionViewModel
@using FlatAdmin.Domain.Entities@ {
    ViewBag.Title =努埃瓦Transaccion
}< H2> @ ViewBag.Title< / H>
< D​​IV>
    @ Html.ActionLink(<<利斯塔德Transacciones,指数)
< / DIV>
< BR />< D​​IV ID =输入面板>
    @using(Html.BeginForm()){
        @ Html.ValidationSummary(真)
        <&字段集GT;
            <传奇> Elegir ACTIVIDAD< /传说>
            < D​​IV CLASS =主编场>
                @ Html.DropDownListFor(型号=> model.Transaction.IdCostCentre,((IEnumerable的< FlatAdmin.Domain.Entities.CostCentre>)Model.AllCostCentres)。选择(选项=>新建SelectListItem
           {
               文字=(选项== NULL无:option.Name)
               值= option.CostCentreId.ToString(),
               选择=(型号!= NULL)及和放大器; (option.CostCentreId == Model.Transaction.IdFrom)
           }),ACTIVIDADES ...)
            < / DIV>
        < /字段集>
        <&字段集GT;
            <传奇> Transaccion< /传说>
            < D​​IV ID =CreateDiv>
                @ Html.Partial(_创建模型)
            < / DIV>
            &所述p为H.;
                <输入类型=提交名称=nextRecordVALUE =比邻Transaccion>>中/>
            &所述; / P>
            &所述p为H.;
                ... O中,对和保存ÿ御宇一拉LISTA德transacciones:LT; BR /><输入类型=提交值=和保存/>
            &所述; / P>        < /字段集>
    }
< / DIV>

控制器动作:

  [HttpPost]
公共虚拟的ActionResult AjaxCreate(交易成交)
{
    如果(ModelState.IsValid)
    {
        service.InsertOrUpdate(事务);
        service.Save();
    }
    service.ChosenCostCentreId = transaction.IdCostCentre;
    TransactionViewModel视图模型=新TransactionViewModel();
    viewModel.Transaction =新交易();
    viewModel.CostCentre = service.ChosenCostCentre;
    viewModel.AllCostCentres = service.AllCostCentres;
    viewModel.AllCurrencies = service.AllCurrencies;
    viewModel.FromAccounts = service.FromAccounts;
    viewModel.ToAccounts = service.ToAccounts;    返回PartialView(_创建视图模型);
}


解决方案

@Darin季米特洛夫想出了一个相关话题的答案。

从本质上讲,HtmlHelpers如Html.EditorFor,Html.TextBoxFor等,首先检查在ModelState中现有的值,然后才在模型中。

因此​​,我需要一个电话:

  ModelState.Clear();

无知是那么的痛苦。

I must be missing something, silly, but here is the problem.

I have a Create action on the Transactions controller. The Create.cshtml uses jQuery to post the form to the server using a call to $.ajax. Debugging shows that everything arrives on the server as expected. I use the form data to update a record: this works fine too. I then return a partial view, passing a model to the view with default data. I can debug and verify that the model is passing nulls and 0s, ie, the default data for my model.

Problem is, what gets sent back to the browser in the response is the old data...!

I can see no reason why. Hopefully, you can...

Note: I am not using any form of output cache.

EDIT 1:

The caching is not happening in the browser. The reason I say that is that I can see in Firebug the response of the call to the AjaxCreate Action. I can also see this in Fiddler.

EDIT 2:

If you look at the code for the Partial View, you will see that each dropdownlist or textbox has the value of @Model.Transaction.[Property] printed out beside it. This, bizarrely, shows the correct value, ie, the defaults for my Transaction object, but the dropdownlists and text boxes stick with the values that were posted to the server rather than the default values for the property each one is supposed to render.

EDIT 3:

I have included the following image, so you can see the values printed to the right of each control that are being passed in. And yet the controls reflect the old data posted to the server in the previous $.ajax call. (The comment shows a date time at the moment of creating the view model, that way I could see things updating).

EDIT 4:

I have found that replacing @Html.EditorFor(...) (see view code below) with @Html.TextBox helpers removes the problem. So, what seems to be happening is that the EditorFor helpers are causing the problem. Why? I have no idea, but will post another, more specific question.

Code and markup as follows:

jQuery:

$(document).ready(function () {

    $('input[name="nextRecord"]').live('click', function () {
        var theForm = $(this).closest('form');
        if ((theForm).valid()) {
            var buttonText = $(this).val();
            var action = "/input/Transactions/AjaxCreate/";
            if (buttonText === "Reset") {
                clearForm(theForm);
            }
            else {
                var targetElement = $('#CreateDiv');
                var _data = theForm.serialize() + '&nextRecord=' + $(this).val();

                $.ajax({
                    url: action,
                    data: _data,
                    cache: 'false',
                    type: 'POST',
                    dataType: 'html',
                    success: function (html) {
                        $(targetElement).html(html);
                        createDatePickers(targetElement);
                        jQuery.validator.unobtrusive.parse(targetElement);
                    }
                });
            }
        }
        return false;
    });
});

Partial View:

@model FlatAdmin.Domain.ViewModels.TransactionViewModel

@* This partial view defines form fields that will appear when creating and editing entities *@

<div class="editor-label">
    Fecha
</div>
<div class="editor-field">
    @Html.EditorFor(model => model.Transaction.TransactionDate, new { @class = "date-picker" })
    @Html.ValidationMessageFor(model => model.Transaction.TransactionDate) @Model.Transaction.TransactionDate.ToString()
</div>

<div class="editor-label">
    Origen:
</div>
<div class="editor-field">
    @Html.DropDownListFor(model => model.Transaction.IdFrom, ((IEnumerable<FlatAdmin.Domain.Entities.Account>)Model.FromAccounts).Select(option => new SelectListItem
{
        Text = (option == null ? "None" : option.AccountName), 
        Value = option.AccountId.ToString(),
        Selected = (Model != null) && (option.AccountId == Model.Transaction.IdFrom)
    }), "Choose...")
    @Html.ValidationMessageFor(model => model.Transaction.IdFrom)@Model.Transaction.IdFrom
</div>

<div class="editor-label">
    Destino:
</div>
<div class="editor-field">
    @Html.DropDownListFor(model => model.Transaction.IdTo, ((IEnumerable<FlatAdmin.Domain.Entities.Account>)Model.ToAccounts).Select(option => new SelectListItem
{
    Text = (option == null ? "None" : option.AccountName),
    Value = option.AccountId.ToString(),
    Selected = (Model != null) && (option.AccountId == Model.Transaction.IdTo)
}), "Choose...")
    @Html.ValidationMessageFor(model => model.Transaction.IdTo)@Model.Transaction.IdTo
</div>
<div class="editor-label">
    Monto
</div>
<div class="editor-field">
    @Html.DropDownListFor(model => model.Transaction.IdCurrency, ((IEnumerable<FlatAdmin.Domain.Entities.Currency>)Model.AllCurrencies).Select(option => new SelectListItem
{
    Text = (option == null ? "None" : option.CurrencyName),
    Value = option.CurrencyId.ToString(),
    Selected = (Model != null) && (option.CurrencyId == Model.Transaction.IdCurrency)
})) 
    @Html.EditorFor(model => model.Transaction.Amount)
    @Html.ValidationMessageFor(model => model.Transaction.Amount) @Model.Transaction.Amount
</div>

<div class="editor-label">
    Comentario
</div>
<div class="editor-field">
    @Html.EditorFor(model => model.Transaction.Comment)
    @Html.ValidationMessageFor(model => model.Transaction.Comment)@Model.Transaction.Comment
</div>

View:

@model FlatAdmin.Domain.ViewModels.TransactionViewModel
@using FlatAdmin.Domain.Entities

@{
    ViewBag.Title = "Nueva Transaccion";
}

<h2>@ViewBag.Title</h2>
<div>
    @Html.ActionLink("<< Lista de Transacciones", "Index")
</div>
<br />

<div id="InputPanel">
    @using (Html.BeginForm()) {
        @Html.ValidationSummary(true)
        <fieldset>
            <legend>Elegir Actividad</legend>
            <div class="editor-field">
                @Html.DropDownListFor(model => model.Transaction.IdCostCentre, ((IEnumerable<FlatAdmin.Domain.Entities.CostCentre>)Model.AllCostCentres).Select(option => new SelectListItem
           {
               Text = (option == null ? "None" : option.Name),
               Value = option.CostCentreId.ToString(),
               Selected = (Model != null) && (option.CostCentreId == Model.Transaction.IdFrom)
           }), "Actividades...")
            </div>
        </fieldset>
        <fieldset>
            <legend>Transaccion</legend>
            <div id="CreateDiv">
                @Html.Partial("_Create", Model)
            </div>
            <p>
                <input type="submit" name="nextRecord" value="Proxima Transaccion >>" />
            </p>
            <p>
                ...o sino, para guardar y volver a la lista de transacciones:<br /><input type="submit" value="Guardar" />
            </p>

        </fieldset>
    }
</div>

Controller Action:

[HttpPost]
public virtual ActionResult AjaxCreate(Transaction transaction)
{
    if (ModelState.IsValid)
    {
        service.InsertOrUpdate(transaction);
        service.Save();
    }
    service.ChosenCostCentreId = transaction.IdCostCentre;
    TransactionViewModel viewModel = new TransactionViewModel();
    viewModel.Transaction =  new Transaction();
    viewModel.CostCentre = service.ChosenCostCentre;
    viewModel.AllCostCentres = service.AllCostCentres;
    viewModel.AllCurrencies = service.AllCurrencies;
    viewModel.FromAccounts = service.FromAccounts;
    viewModel.ToAccounts = service.ToAccounts;

    return PartialView("_Create", viewModel);
}

解决方案

@Darin Dimitrov came up with the answer in a related thread.

Essentially, the HtmlHelpers such as Html.EditorFor, Html.TextBoxFor, etc, check first in the ModelState for existing values, and ONLY then in the Model.

As a result, I needed a call to:

ModelState.Clear();

Ignorance is so painful.

这篇关于MVC 3 + $阿贾克斯 - 反应似乎从缓存局部视图输出的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆