【问题标题】:Submitting partial view data from parent view从父视图提交部分视图数据
【发布时间】:2014-12-03 09:28:13
【问题描述】:

如何从父视图提交部分视图数据。

我是 MVC 的新手,
我创建了一个包含编辑器控件的局部视图 _CurrentData - 文本框等
并在主视图中添加了提交按钮:

<div class="row">
    <div class="col-md-12">
        @Html.Partial("_CurrentData", Model.CurrentItemDetails)
    </div>
</div>
<div class="row">
    <div class="col-md-2 col-md-offset-5">
        <div>
            <input type="button" class="btn btn-primary" value="Submit" id="btnSubmit"/>
            &nbsp;&nbsp;
            <input type="button" class="btn btn-primary" value="Cancel" id="btnCancel" />
            <br/><br />
        </div>
    </div>
</div>

视图模型

public class ProductionViewModel
{
    public ItemDetails CurrentItemDetails { get; set; }
}

public class ItemDetails
{
    public int ID { get; set; }
    public string Name { get; set; }
}

查看

<div class="panel panel-default">
    <div class="panel-heading">
        <h3 class="panel-title">Editor</h3>
    </div>
    <div class="panel-body">
        <div class="row form-group">
            <div class="col-sm-4 control-label text-right">
                <strong>Name:</strong>
            </div>
            <div class="col-sm-8 control-label">
                @Html.TextBoxFor(m => m.Name , new { @class = "form-control" })
            </div>
        </div>
    </div>
</div>

现在单击“btnSubmit”时,我想将 _CurrentData 视图中的数据提交到服务器,然后刷新部分视图,
如何做到这一点?

【问题讨论】:

  • 希望我理解了你的问题。你尝试过 ajax post 方法吗。你可以建立一个模型并将其发送到控制器。 api.jquery.com/jquery.post
  • 也许这会对你有所帮助:How to send data from partial View
  • This 是正确的做法。
  • @Sippy, Martin:会导致整页重新加载
  • @Hsakarp 从部分视图中编写提交代码是一种好习惯吗?我的意思是控件在局部视图中,我们正在主视图中编写 HTTP 后代码。

标签: javascript jquery asp.net-mvc razor


【解决方案1】:

你的要求

您要求的功能是 AJAX。 AJAX 请求是“异步”的,这在最基本的层面上意味着可以发起和响应 HTTP 请求,而无需刷新页面。

正如有人在对您的问题的评论中所写的那样,可以使用 jQuery,并且确实提供了一种处理 AJAX 请求的好方法,但是如果您仅针对 AJAX 请求包含整个 jQuery 库,很多人可能会哭泣。

JavaScript

所以在 JavaScript 中这liiiiiiittle 有点复杂,有一些例子here。我不会仅仅因为我现在没有太多时间而向您展示如何在 JavaScript 中执行此操作,但我可能稍后会更新答案。如果可以的话,我可能会建议考虑这样做。

jQuery

在 jQuery 中,这很容易。 AJAX 请求的文档是here

基本上,您需要做的是向服务器发出请求,以便它可以更新您的局部视图数据,然后返回新的局部视图供您替换当前的 HTML。它看起来像:

$.fn.serializeObject = function () {
    var o = {};
    var a = this.serializeArray();
    $.each(a, function () {
        if (o[this.name]) {
            if (!o[this.name].push) {
                o[this.name] = [o[this.name]];
            }
            o[this.name].push(this.value || '');
        } else {
            o[this.name] = this.value || '';
        }
    });
    return o;
};

$.ajax({
    url: '@Url.Content("~/Controller/_CurrentData")',
    type: 'POST',
    data: {
        //partialViewForm relates to the form element in your partial view
        model: JSON.stringify($('#partialViewForm').serializeObject());
    },
    success: function (response) {
        if (response) {
            //partialViewDiv relates to the div in which your partial view is rendered
            $('#partialViewDiv').html(response);
        }
    },
    error: function (xhr, ajaxOptions, thrownError) { alert(xhr.status); alert(thrownError); }
});

上面假设你有这样的东西作为你的控制器方法:

[HttpPost]
public ActionResult _CurrentData(ItemDetails model)
{
    //do stuff with model here
    return PartialView("_CurrentData", model);
}

所以这基本上就是您联系控制器的方式。为了从您的网页调用该 ajax,您需要在表单中的局部视图中有一个按钮,您可以使用 event.preventDefault() 覆盖该按钮。

【讨论】:

  • 或者你可以简单地使用$.post('@Url.Action("_CurrentData", "yourControllerName")', $('#partialViewForm').serialize(), function(response) { $('#partialViewDiv').html(response); });
【解决方案2】:

其实在浏览器端看情况并没有partial viewparent view这样的说法。浏览器只看到一个 html 文档。 Html.Partial 特别是 PartialViews 仅在服务器端有意义,它们确实可以帮助您。它使您能够在多个页面上重用部分视图,并在一个地方修改所有视图。当Razor渲染这个cshtml文件时,开始从上到下渲染,当遇到@Html.Partial("something")它执行返回Html编码 string 并显示返回的字符串。毕竟,Razor 返回一个完整的 html 页面。因此,当您提交来自 html 的数据时,唯一重要的是哪个输入类型具有哪个 name 属性。

解决方案 1:不使用 Ajax 根据您的主视图,您的 get 方法是这样的。

// GET: Item
        public ActionResult MainView()
        {
            var _itemDetail = new ItemDetails { ID = 1, Name = "Item1" }; //you get this item somewhere maybe db
            var pvm = new ProductionViewModel();
            pvm.CurrentItemDetails = _itemDetail;  //add item to viewmodel
            return View(pvm);
        }

我假设您有表单标签,只需将您的按钮类型更改为提交

@using(Html.BeginForm()){
<div class="row">

    <div class="col-md-12">

        @Html.Partial("_CurrentData", Model.CurrentItemDetails)

    </div>
</div>
<div class="row">
    <div class="col-md-2 col-md-offset-5">
        <div>
            <input type="submit" class="btn btn-primary" value="Submit" id="btnSubmit" />
            &nbsp;&nbsp;
            <input type="button" class="btn btn-primary" value="Cancel" id="btnCancel" />
            <br /><br />
        </div>
    </div>
</div>
}

并将您的发布操作添加到控制器,这非常好。

[HttpPost]
        public ActionResult MainView(ItemDetails submittedItem)
        {
            //do stuff with model like persistence
            var pvm = new ProductionViewModel();
            pvm.CurrentItemDetails = submittedItem;
            return View(pvm);
        }

这将返回与新项目相同的视图

解决方案 2: 使用 Jquery 的 Ajax 这个解决方案已经给出。您将有两个选择;从服务器返回部分视图并将旧内容替换为从服务器返回的内容或返回 json 并通过 dom 操作更改内容。两种方法都有缺点。 Sippy 的回答很完美,我想添加的是代替 jquery ajax 方法的 load 方法对于返回静态视图更合理。

$("#partialViewDiv").load('@Url.Content("~/Controller/_CurrentData")');

解决方案 3:使用双向数据绑定或 Angular 等框架 当您想刷新局部视图时,您可能需要一些服务器生成的额外信息,例如新创建项目的 id。这就是为什么您需要与服务器交谈的原因,因为您已经有了动态的局部视图的新输入值。可能您想在同一页面某处的列表中显示所有已保存的项目,并且在从服务器返回创建的项目后,您必须手动添加它。因此,如果您的页面需要这样的情况,最好的方法是使用 Angular 等框架。这样,您可以刷新局部视图并毫不费力地做很多事情。我的 Demo 只是为了演示,你可以遵循许多设计原则。

这是主视图

<div ng-app="ItemApp" ng-controller="ItemController">
    <form name="newTopicForm" data-ng-submit="save()">
        <div class="row">
            <div class="col-md-12">
                @Html.Partial("_CurrentData", Model.CurrentItemDetails)
            </div>
        </div>
        <div class="row">
            <div class="col-md-2 col-md-offset-5">
                <div>
                    <input type="submit" class="btn btn-primary" value="Submit" id="btnSubmit" />
                    &nbsp;&nbsp;
                    <input type="button" class="btn btn-primary" value="Cancel" id="btnCancel" />
                    <br /><br />
                </div>
            </div>
        </div>
    </form>
</div>

局部视图

<div class="panel panel-default">
    <div class="panel-heading">
        <h3 class="panel-title">Editor</h3>
    </div>
    <div class="panel-body">
        <div class="row form-group">
            <div class="col-sm-4 control-label text-right">
                <strong>Name:</strong>
            </div>
            <div class="col-sm-8 control-label">
    @Html.TextBoxFor(m => m.Name, new { @class = "formcontrol",data_ng_model="item.name",data_ng_init="item.name="+"'"+@Model.Name+"'"})
            </div>
        </div>
    </div>
</div>

文本框通过 ng-model 属性绑定到 item.name,因此我们无需担心刷新视图。当 item.name 改变时,视图也会改变。(双向数据绑定) 包括 Angular js,这是自定义 js

var myApp = angular.module('ItemApp', []);
myApp.controller('ItemController', function ($scope, $http,$q) {
    $scope.itemList = {};
    $scope.save = function () {
        $http.post("mainview", $scope.item).
        then(function (result) {

         $scope.item.name = result.data.Name; //update from server
                                              //it is enoguh to refresh 
                                              //your partial view data
         itemList.splice(0, 0, result.data);//add list may be you need to
                                               //display in the view
        },
        function () {
            console.log(error);
        });
    };
});

和服务器端代码

[HttpPost]
        public ActionResult MainView(ItemDetails SubmittedItem)
        {
            //do stuff with model like persistence
            SubmittedItem.ID = 1;

            return Json(SubmittedItem);
        }

你只需要处理对象所有视图操作在使用角度时都是通过两种方式数据绑定完成的。

【讨论】:

    【解决方案3】:

    是的,主视图是纯 HTML 或由多个部分视图 + 主视图组成,当它在浏览器中呈现时,将被视为一个 HTML 而不是部分。也就是说,您将可以访问对于 DOM,它要么在部分视图中,要么在主视图中。所以,根据我的个人经验,如果您决定使用 Jquery post 方法通过构建自己的模型/视图模型来帮助,我们将提交按钮放在哪里并不重要它。

    但是是的,在某些情况下,您将在局部视图的每个级别上使用局部更新按钮

    @using (Ajax.BeginForm
    

    【讨论】:

    • 这是对这个问题的简单回答
    【解决方案4】:

    解决方案 1

    您可以简单地将inputs 包装在Ajax form 元素内的主页中,并在其中调用@Html.Partial("_CurrentData", Model.CurrentItemDetails),一切都会正常工作。

    解决方案 2

    不使用带有一些 JavaScript 代码的form 标记来查找目标inputs,只需点击btnSubmit 元素(define click event)然后serialize 他们准备发送到服务器的操作方法。

    两个解决方案的共同部分是编写一个 ajax 方法来响应更新页面而不刷新,例如:

    public JsonResult GetResponse(ItemDetails model) {            
        return Json(/*data*/, /*behavior*/);
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多