MVC根据所选选项动态更改创建表单并将其保存在数据库

时间:2016-07-14 17:37:12

标签: c# jquery ajax asp.net-mvc asp.net-mvc-4

我有4 Models Post,Car,Category,SubCategory。 Car有一些额外的属性,并且还继承Post,Post Model中的所有内容,包括CategoryID和SubCategoryID的属性。我需要创建一个View,可以动态更改以便能够保存汽车。用户首先看到两个dropdown列表中的类别和子类别,在选中后,它会加载右PartialView。它很好,但由于一些原因我无法将其保存在数据库中。

首先,我不知道在哪里为页面声明model,如果它在创建View中 - 意味着它无法更改,因为我只希望输入字段出现并动态更改但不应重新加载页面。这也意味着Car Model有一些额外的属性,stringint,我无法创建具有ViewModel所有可能属性的string不是nullable。 如果在model中声明PartialView,则表示我可以为Car和Post创建单独的ViewModel,但表单标记将位于PartialView和{{1类别和子类别的列表在创建dropdown中的此表单标记之外,因为它不应更改。当表单发布时,我收到错误,因为我使用View来获取CategoryID和SubCategoryID。我需要以某种方式解决这个问题。

我尝试使用Request.Form["..ID"];,但是出现了类别ID和子类别ID的空条目错误,只传递了表单标记中的值。

Ajax

Models

创建public class Category { public int CategoryID { get; set; } public string Name { get; set; } } public class SubCategory { public int SubCategoryID { get; set; } [Required] public string Name { get; set; } [ForeignKey("CategoryID")] public virtual Category Category { get; set; } public int? CategoryID { get; set; } } public class Post { public int PostID { get; set; } public string Title { get; set; } public string Msg { get; set; } [DataType(DataType.Currency)] public decimal Price { get; set; } public string PostCode { get; set; } [DataType(DataType.ImageUrl)] public string MainPhotoPath { get; set; } public DateTime PostedAt { get; set; } public bool Active { get; set; } public string ApplicationUserId { get; set; } [ForeignKey("SubCategoryID")] public virtual SubCategory SubCategory { get; set; } public int SubCategoryID { get; set; } public int CategoryID { get; set; } public string CityName { get; set; } } public class Car : Post { public string Make { get; set; } public int Year { get; set; } public int EngineSize { get; set; } public int Mileage { get; set; } public string FuelType { get; set; } public string Transmission { get; set; } }

View

选择类别和子类别的菜单

@using Mvc.CascadeDropDown

@{
    ViewBag.Title = "Create";
}
<div class="row">
<div class="col-lg-12">
    <div class="text-center">
        <h2>Add a new Post</h2>
        <h3 id="CityDiv">City: @ViewBag.Location</h3>
    </div>
    <div class="col-lg-12">
        @Html.Action("Menu")
        <div id="createNewPost">

        </div>
    </div>        
</div>
</div>
<script type="text/javascript">
$("#SubCategoryID").click(function () {
    var selectedSubCategory = $("#SubCategoryID").val();
    if (selectedSubCategory == 4) {
        var url = "/Posts/CarPartial/";

        $.ajax({
            url: url,
            cache: false,
            type: "POST",
            success: function (data) {
                $("#createNewPost").html(data);
            },
            error: function (reponse) {
                alert("error : " + reponse);
            }
        });
    }        
    else {
        var url = "/Posts/PostPartial/";

        $.ajax({
            url: url,
            cache: false,
            type: "POST",
            success: function (data) {
                $("#createNewPost").html(data);
            },
            error: function (reponse) {
                alert("error : " + reponse);
            }
        });
    }
});
$("#CreatePostFormID").submit(function () {
    var _categoryId = $("#CategoryID").val();
    var _subcategoryId = $("#SubCategoryID").val();
    var url = "/Posts/Create/";

    $.ajax({
        url: url,
        data: { cId: _categoryId, subId: _subcategoryId },
        cache: false,
        type: "POST",
        success: function (data) {
            alert("ok");
        },
        error: function (reponse) {
            alert("error : " + reponse);
        }
    });
});
</script>
@section Scripts {
@Scripts.Render("~/bundles/jqueryval")
}
如果子类别仅需要帖子@model PostIt.Models.DropDown <h4> Please choose a category first </h4> @using (Html.BeginForm()) { @Html.DropDownListFor(m => m.CategoryModel, new SelectList(Model.CategoryModel, "CategoryID", "Name"), new { @id = "CategoryID", @class = "form-control col-md-offset-2 margin-bottom" }) <select id="SubCategoryID" name="SubCategoryID" class="form-control col-md-offset-2 margin-bottom"></select> } <script language="javascript" type="text/javascript"> $(window).load(function () { $("#CategoryID").click(function () { var _categoryId = $("#CategoryID").val(); var procemessage = "<option value='0'> Please wait...</option>"; $("#SubCategoryID").html(procemessage).show(); var url = "/Posts/GetSubCategoryById/"; $.ajax({ url: url, data: { categoryid: _categoryId }, cache: false, type: "POST", success: function (data) { var markup = "<option value='0'>Select a subcategory</option>"; for (var x = 0; x < data.length; x++) { markup += "<option class='selectedSubCategory' value=" + data[x].Value + ">" + data[x].Text + "</option>"; } $("#CategoryID").val(_categoryId); $("#SubCategoryID").html(markup).show(); }, error: function (reponse) { alert("error : " + reponse); } }); }); }); </script>

,则PartialView createNewPost内加载

div

Model

@model PostIt.Models.PostViewModel @using (Html.BeginForm("Create", "Posts", FormMethod.Post, new { enctype = "multipart/form-data", id = "CreatePostFormID" })) { @Html.AntiForgeryToken() <div class="form-horizontal"> <div class="form-group"> @Html.LabelFor(model => model.Title, htmlAttributes: new { @class = "control-label col-md-2" }) <div class="col-md-10"> @Html.EditorFor(model => model.Title, new { htmlAttributes = new { @class = "form-control" } }) @Html.ValidationMessageFor(model => model.Title, "", new { @class = "text-danger" }) </div> </div> <div class="form-group"> @Html.LabelFor(model => model.Msg, htmlAttributes: new { @class = "control-label col-md-2" }) <div class="col-md-10"> @Html.EditorFor(model => model.Msg, new { htmlAttributes = new { @class = "form-control" } }) @Html.ValidationMessageFor(model => model.Msg, "", new { @class = "text-danger" }) </div> </div> <div class="form-group"> @Html.LabelFor(model => model.Price, htmlAttributes: new { @class = "control-label col-md-2" }) <div class="col-md-10"> @Html.EditorFor(model => model.Price, new { htmlAttributes = new { @class = "form-control" } }) @Html.ValidationMessageFor(model => model.Price, "", new { @class = "text-danger" }) </div> </div> <div class="form-group"> @Html.LabelFor(model => model.PostCode, htmlAttributes: new { @class = "control-label col-md-2" }) <div class="col-md-10"> @Html.EditorFor(model => model.PostCode, new { htmlAttributes = new { @class = "form-control" } }) @Html.ValidationMessageFor(model => model.PostCode, "", new { @class = "text-danger" }) </div> </div> <div class="form-group"> @Html.LabelFor(model => model.MainPhotoPath, htmlAttributes: new { @class = "control-label col-md-2" }) <div class="col-md-10"> @Html.TextBoxFor(model => model.MainPhotoPath, new { type = "file" }) @Html.ValidationMessageFor(model => model.MainPhotoPath, "", new { @class = "text-danger" }) </div> </div> <div class="form-group"> <div class="col-md-offset-2 col-md-10"> <input type="submit" value="Create" class="btn btn-default" id="SubmitID" /> | @Html.ActionLink("Cancel", "Index") </div> </div> </div> } 创建帖子。

ActionMethod

1 个答案:

答案 0 :(得分:1)

我不是故意要转储过多的代码而且我已经从中吸取了教训......

如果有人正在努力解决同样的问题,答案如下:

使用model标记声明PartialView中的@using (Html.BeginForm,以便您可以根据model创建表单。创建表单可以通过Ajax动态更改,因此基本上一个创建表单可以处理任何模型。

由于dropdown列表包含必要的CategoryID和SubCategoryID的值在表单标记之外,因此它不会传递给控制器​​,即使在顶部使用Ajax,它也只会破坏它。首先它会调用ActionResult,但没有为ID传递值,返回错误,甚至不会调用Ajax函数。

要解决此问题,在右侧PartialView的控制器中创建model时,我会随身携带ID值。

Ajax致电发布PartialView

var url = "/Posts/PostPartial/";

        $.ajax({
            url: url,
            data: { cid : selectedCategory, sid : selectedSubCategory },
            cache: false,
            type: "POST",
            success: function (data) {
                $("#createNewPost").html(data);
            },
            error: function (reponse) {
                alert("error : " + reponse);
            }
        });
控制器内的

ActionResult返回右PartialView。在这种情况下,它是一个帖子。

public ActionResult PostPartial(int cid, int sid)
    {
        PostViewModel viewmodel = new PostViewModel();
        viewmodel.CategoryID = cid;
        viewmodel.SubCategoryID = sid;
        return PartialView("CreatePost", viewmodel);
    }

上面的Create ActionResult工作正常,但是名为PostViewModel的ViewModel必须具有CategoryID和SubCategoryID的属性,并且控制器中必须bind属性才能创建ActionResult