如何正确使用带有 Ajax Begin 表单的局部视图

Posted

技术标签:

【中文标题】如何正确使用带有 Ajax Begin 表单的局部视图【英文标题】:How to correctly use Partial views with Ajax Begin form 【发布时间】:2016-05-02 09:49:14 【问题描述】:

我的 index.cshtml 中有以下代码

@using Kendo.Mvc.UI;
@using xx.Relacionamiento.Modelo.Bussiness.Entities;
@using xx.Relacionamiento.Modelo.Bussiness.Entities.Custom;

<script src="~/Scripts/jquery.unobtrusive-ajax.min.js"></script>
<script src="~/Scripts/jquery.validate.js"></script>
<script src="~/Scripts/jquery.validate.unobtrusive.min.js"></script>

@model PresupuestosGenerale

@
    ViewBag.Title = "Index";
    Layout = "~/Views/Shared/_Layout.cshtml";

    

<div class="">

    <div id="ContenedorPresupuestoGeneral">
        @Html.Partial("CreateOrEditPresupuestoGeneralxx", Model)
    </div>
    <br />
    <br />

然后我有以下PartialView

@using xx.Relacionamiento.Modelo.Bussiness.Entities.Enumeraciones;
@using xx.Relacionamiento.Modelo.Bussiness.Entities;
@using Kendo.Mvc.UI;


@model PresupuestosGenerale
<div class="panel panel-default">
    <div class="panel-heading">
        @using (Ajax.BeginForm("CreateOrEditPresupuestoGeneralxx", new AjaxOptions()  HttpMethod = "Post", UpdateTargetId = "ContenedorPresupuestoGeneral", InsertionMode = InsertionMode.Replace ))
        
            @Html.HiddenFor(h => h.PresupuestoGeneralId)
            @Html.Hidden("Categoria",CategoriaEvento.xx.ToString())
            <div class="row">
                <div class="col-lg-6 col-md-6 col-sm-6 col-xs-6">
                    <label>Presupuesto Global xx</label>
                    <br />
                    @(Html.Kendo().NumericTextBoxFor(e => e.PresupuestoGlobal)
                    .Decimals(0)
                    .DecreaseButtonTitle("Decrementar")
                    .IncreaseButtonTitle("Incrementar")
                    .Format("c0")
                    .HtmlAttributes(new  style = "width:99%;" )
                    .Max(1000000000000000000)
                    .Min(1)
                    .Step(100000)
                    .Placeholder("Presupuesto General xx"))
                    @Html.ValidationMessageFor(v => v.Valor, "", new  @style = "color: rgba(247, 20, 10, 0.97);" )
                </div>
                <div class="col-md-3">
                    <br />
                    <input type="submit" class="form-control btn btn-primary" value="Guardar Presupuesto" onclick="SetMostrarVentana();" />
                </div>
            </div>
        


    </div>
</div>
<script type="text/javascript">

    $(function () 
        MostrarVentanaLoading = false;
        @if (!string.IsNullOrEmpty(ViewBag.MensajeError))
        
            @:mostrarMensajeAlertGlobal("@ViewBag.MensajeError",15000)
        
        else if (!string.IsNullOrEmpty(ViewBag.MensajeSuccess))
        
            @:mostrarMensajeAlertSuccessGlobal("@ViewBag.MensajeSuccess", 15000);
        
    );

</script>

然后在我的控制器上,我的业务逻辑会根据条件返回不同的内容

 public ActionResult CreateOrEditPresupuestoGeneralxx(PresupuestosGenerale presupuestoGeneralxx)
        
            try
            
                ModelState.Remove("PresupuestoGlobal");

                if (presupuestoGeneralxx == null)
                
                    return PartialView();
                
                if (!ModelState.IsValid)
                
                    return PartialView(presupuestoGeneraxx);
                

                if (presupuestoGeneralxx.Valor < 1)
                
                    ModelState.AddModelError("Valor", "Por favor ingrese un presupuesto total");
                    return PartialView(presupuestoGeneralxx);
                

因此,当用户提交表单时,索引视图中的容器将替换为新的 html。

代码运行良好,但是我觉得代码很丑,不可维护且难以阅读。

我的问题是,对于 asp.net mvc 和 ajax,是否有更好、更有条理的方式来实现同样的事情,并且代码更易读?

【问题讨论】:

为什么你觉得这是不可维护的? 感觉像丑陋的代码。包含部分视图的视图,它会更新主视图上的 div。 如果你想使它可维护,你已经编写了很好的代码,然后在你编写的代码上使用适当的 cmets 以理解其他 你为什么用局部分割视图?只是出于 ajax 或任何其他原因? 唯一可以改进的就是这一行:ModelState.Remove("PresupuestoGlobal");这是一份综合指南(ModelState 未更改):pluralsight.com/guides/ 【参考方案1】:

我会重构将 ajax 表单移到部分之外的视图。这样,在表单内呈现的完整部分在 ajax 帖子上刷新,不知道容器结构并解耦,每个视图都有自己的责任:

索引.cshtml

<div class="panel panel-default">
    <div class="panel-heading">
        @using (Ajax.BeginForm("CreateOrEditPresupuestoGeneralxx", new AjaxOptions()  HttpMethod = "Post", UpdateTargetId = "form-content", InsertionMode = InsertionMode.Replace ))
        
            <div id="form-content">
                @Html.Partial("CreateOrEditPresupuestoGeneralxx", Model)
            </div>
        
    </div>
</div>

CreateOrEditPresupuestoGeneralxx.cshtml

@using xx.Relacionamiento.Modelo.Bussiness.Entities.Enumeraciones;
@using xx.Relacionamiento.Modelo.Bussiness.Entities;
@using Kendo.Mvc.UI;

@model PresupuestosGenerale

@Html.HiddenFor(h => h.PresupuestoGeneralId)
@Html.Hidden("Categoria",CategoriaEvento.xx.ToString())
<div class="row">
...

【讨论】:

这可能比原来的要好,但是它在部分中有一个提交按钮,但它提交的表单在部分之外。这对我来说似乎有点乱。 但这不是问题。这里partial的作用是让通过Ajax提交和redeaw表单内容。部分知道是表单内容,但不知道表单发布在哪里,是否是Ajax等,只知道它是表单内容,按钮是表单内容的一部分 提交按钮有一个onclick事件。表单是否需要了解的不仅仅是表单本身的内容,取决于该事件的作用。但是,是的,你几乎肯定是对的。 我没有注意到,但现在你指出了,这不是问题。首先,我不会在标记内绑定事件,而是在文档准备好时不显眼。通过这种方式,您可以决定是将事件代码作为部分的一部分,还是作为 form.submit 放在容器中。也许第二个会更干净,这取决于事件处理程序的作用【参考方案2】:

这是我在一些项目中使用的示例之一。在这个例子中,不仅PartialView被渲染,DropdownList的值也被传递给PartialView并显示在上面。

查看:

<div id="divPartialView">
    @Html.Partial("~/Views/MyPartialView.cshtml", Model)
</div>


$(document).ready(function ()  
    $(".SelectedCustomer").change(function (event) 
        $.ajax(
            url: '@Url.Action("GetPartialDiv", "Home")',
            data:  id: $(this).val() /*add other additional parameters */ ,
            cache: false,
            type: "POST",
            dataType: "html",
            success: function (data, textStatus, XMLHttpRequest) 
                SetData(data);
            ,
            error: function (data)  onError(data); 
        );
    );

    function SetData(data) 
        $("#divPartialView").html(data); //HTML DOM replace
     
);

控制器:

[HttpPost]
public PartialViewResult GetPartialDiv(int id /* ddl's selectedvalue */)

    Models.GuestResponse guestResponse = new Models.GuestResponse();
    guestResponse.Name = "this was generated from this ddl id:"; 
    return PartialView("MyPartialView", guestResponse);

希望这会有所帮助...

【讨论】:

以上是关于如何正确使用带有 Ajax Begin 表单的局部视图的主要内容,如果未能解决你的问题,请参考以下文章

实现带有验证码的ajax局部刷新登录界面

使用带有 AJAX 表单的后退按钮?

如何使用 JQuery 和 formData 正确获取表单数据

如何使用带有 Recaptcha 的 AJAX 发送表单? [拉拉维尔]

如何使用 jQuery 的 ajax 方法调用局部视图

如何使用 jquery/ajax 正确刷新包含表单的 div?