MVC没有传递值

时间:2017-12-10 19:41:37

标签: c# asp.net-mvc

我正在使用asp.net MVC为数据库访问提供前端。

问题:我视图中的数据没有到达我的控制器。

具体来说,我有一个我的CreditCard模型的创建视图,其中用户输入类型,ccnumber,cardfirstname,cardlastname,expirationdate,cvc和addressid。 (addressid是由数据库生成的int,用于唯一标识现有地址,所有其他都是字符串)

@model FlightBooking.Models.CreditCard

@{
    ViewBag.Title = "Create";
}

<h2>Create</h2>


@using (Html.BeginForm())
{
    @Html.AntiForgeryToken()

<div class="form-horizontal">
    <h4>Credit Card</h4>
    <hr />
    @Html.ValidationSummary(true, "", new { @class = "text-danger" })

    <div class="form-group">
        @Html.LabelFor(model => model.Type, new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.EditorFor(model => model.Type, new { htmlAttributes = new { @class = "form-control" } })
            @Html.ValidationMessageFor(model => model.Type, "", new { @class = "text-danger" })
        </div>
    </div>

    <div class="form-group">
        @Html.LabelFor(model => model.CcNumber, htmlAttributes: new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.EditorFor(model => model.CcNumber, new { htmlAttributes = new { @class = "form-control" } })
            @Html.ValidationMessageFor(model => model.CcNumber, "", new { @class = "text-danger" })
        </div>
    </div>

    <div class="form-group">
        @Html.LabelFor(model => model.CardFirstName, htmlAttributes: new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.EditorFor(model => model.CardFirstName, new { htmlAttributes = new { @class = "form-control" } })
            @Html.ValidationMessageFor(model => model.CardFirstName, "", new { @class = "text-danger" })
        </div>
    </div>

    <div class="form-group">
        @Html.LabelFor(model => model.CardLastName, htmlAttributes: new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.EditorFor(model => model.CardLastName, new { htmlAttributes = new { @class = "form-control" } })
            @Html.ValidationMessageFor(model => model.CardLastName, "", new { @class = "text-danger" })
        </div>
    </div>

    <div class="form-group">
        @Html.LabelFor(model => model.ExpirationDate, htmlAttributes: new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.EditorFor(model => model.ExpirationDate, new { htmlAttributes = new { @class = "form-control" } })
            @Html.ValidationMessageFor(model => model.ExpirationDate, "", new { @class = "text-danger" })
        </div>
    </div>

    <div class="form-group">
        @Html.LabelFor(model => model.Cvc, htmlAttributes: new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.EditorFor(model => model.Cvc, new { htmlAttributes = new { @class = "form-control" } })
            @Html.ValidationMessageFor(model => model.Cvc, "", new { @class = "text-danger" })
        </div>
    </div>

    <!-- TODO: This needs to be a dropdown with address info -->
    <div class="form-group">
        @Html.LabelFor(model => model.AddressID, htmlAttributes: new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.EditorFor(model => model.AddressID, new { htmlAttributes = new { @class = "form-control" } })
            @Html.ValidationMessageFor(model => model.AddressID, "", new { @class = "text-danger" })
        </div>
    </div>

    <div class="form-group">
        <div class="col-md-offset-2 col-md-10">
            <input type="submit" value="Save" class="btn btn-default" />
        </div>
    </div>
</div>
}

<div>
    @Html.ActionLink("Back to List", "Index", "Account")
</div>

@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
}

我的控制器获取该信息并使用它将信用卡信息插入数据库。

using System;
using System.Net;
using System.Web.Mvc;
using FlightBooking.Models;
using Microsoft.Ajax.Utilities;

namespace FlightBooking.Controllers
{
    public class CreditCardController : Controller
    {
        private static readonly SqlParser Parser = new SqlParser();
        private static readonly SqlClient Client = new SqlClient(Parser);

        [ChildActionOnly]
        public ActionResult Index()
        {
            var creditCards = Client.GetCreditCards(CurrentUser.Email);
            return PartialView("Index", creditCards);
        }

        public ActionResult Create()
        {
            return View();
        }

        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Create([Bind(Include = "Type,CcNumber,CardFirstName,CardLastName,ExpirationDate,Cvc,AddressID")] CreditCard creditCard)
        {
            try
            {
                if (ModelState.IsValid)
                {
                    Client.InsertCreditCard(CurrentUser.Email, creditCard.Type, creditCard.CcNumber, creditCard.CardFirstName,
                        creditCard.CardLastName, creditCard.ExpirationDate, creditCard.Cvc, creditCard.AddressID);

                    return RedirectToAction("Index", "Account");
                }
            }
            catch (Exception /* dex */)
            {
                //Log the error (uncomment dex variable name and add a line here to write a log.)
                ModelState.AddModelError("", "Unable to save changes. Try again, and if the problem persists, see your system administrator.");
            }

            return RedirectToAction("Index", "Account");
        }

        public ActionResult Edit(string id)
        {
            if (id.IsNullOrWhiteSpace())
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
            var creditCard = Client.GetCreditCard(id);

            if (creditCard == null)
            {
                return HttpNotFound();
            }
            return View(creditCard);
        }

        [HttpPost, ActionName("Edit")]
        [ValidateAntiForgeryToken]
        public ActionResult EditPost(string id)
        {
            if (id.IsNullOrWhiteSpace())
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }

            var creditCard = Client.GetCreditCard(id);
            ModelState.Remove("id");
            if (TryUpdateModel(creditCard, "", new[] { "Type", "CcNumber", "CardFirstName", "CardLastName", "ExpirationDate", "Cvc", "AddressID" }))
            {
                try
                {
                    Client.UpdateCreditCard(creditCard.Type, creditCard.CcNumber, creditCard.CardFirstName,
                        creditCard.CardLastName, creditCard.ExpirationDate, creditCard.Cvc, creditCard.AddressID);

                    return RedirectToAction("Index", "Account");
                }
                catch (Exception /* dex */)
                {
                    //Log the error (uncomment dex variable name and add a line here to write a log.
                    ModelState.AddModelError("", "Unable to save changes. Try again, and if the problem persists, see your system administrator.");
                }
            }

            return View(creditCard);
        }

        public ActionResult Delete(string id)
        {
            if (id.IsNullOrWhiteSpace())
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }

            var creditCard = Client.GetCreditCard(id);
            if (creditCard == null)
            {
                return HttpNotFound();
            }
            return View(creditCard);
        }

        [HttpPost, ActionName("Delete")]
        [ValidateAntiForgeryToken]
        public ActionResult DeleteConfirmed(string id)
        {
            Client.DeleteCreditCard(CurrentUser.Email, id);
            return RedirectToAction("Index", "Account");
        }
    }
}

点击保存将我发回我的帐户索引视图,没有错误消息。在调试时,我注意到我的ModelState没有以AddressID的键条目结束,并且生成的CreditCard对象的addressID为0.所有其他属性都正确写入ModelState和CreditCard对象。

this.ValueProvider [5] .Non-Public members._values(它是System.Web.Mvc.JqueryFormValueProvider)显示所有七个属性和一个额外的_RequestVerificationToken。

有人可以解释为什么我的AddressID没有从ValueProvider到ModelState吗?

下面是我的CreditCard模型,以防我在其中所做的事情正在排除正确传递数据。

using System;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;

namespace FlightBooking.Models
{
    public class CreditCard
    {
        // TODO: input restrictions
        [DisplayName("Provider")]
        public string Type { get; set; }
        [DisplayName("Number")]
        public string CcNumber { get; set; }
        [DisplayName("First Name")]
        public string CardFirstName { get; set; }
        [DisplayName("Last Name")]
        public string CardLastName { get; set; }
        [DisplayName("Expiration")]
        [DisplayFormat(DataFormatString="{0:MM/yy}", ApplyFormatInEditMode = true)]
        public DateTime ExpirationDate { get; set; }
        [DisplayName("CVC")]
        public string Cvc { get; set; }
        public int AddressID;
        public Address Address { get; set; }

        public CreditCard() { }

        public CreditCard(string type, string ccNumber, string cardFirstName, string cardLastName, DateTime expirationDate,
            string cvc, Address address)
        {
            Type = type;
            CcNumber = ccNumber;
            CardFirstName = cardFirstName;
            CardLastName = cardLastName;
            ExpirationDate = expirationDate;
            Cvc = cvc;
            Address = address;
        }

        public CreditCard(string type, string ccNumber, string cardFirstName, string cardLastName, DateTime expirationDate,
            string cvc, int addressID)
        {
            Type = type;
            CcNumber = ccNumber;
            CardFirstName = cardFirstName;
            CardLastName = cardLastName;
            ExpirationDate = expirationDate;
            Cvc = cvc;
            AddressID = addressID;
        }
    }
}

PS:此处包含的所有信用卡信息都是随机生成的,实际上并不代表实际卡片,因此我现在并不担心安全问题。

PPS:值得注意的是,在尝试编辑现有的信用卡时,它也遇到了同样的问题。它正确地使用初始值填充表单,但提交编辑结果的情况与AddressID不会在我的控制器中结束的情况相同,尽管它位于ValueProvider中。编辑包含在下面以供参考。

@model FlightBooking.Models.CreditCard

@{
    ViewBag.Title = "Edit";
}

<h2>Edit</h2>


@using (Html.BeginForm())
{
    @Html.AntiForgeryToken()

    <div class="form-horizontal">
        <h4>Credit Card</h4>
        <hr />
        @Html.ValidationSummary(true, "", new { @class = "text-danger" })
        @Html.HiddenFor(model => model.Type)

        <div class="form-group">
            @Html.LabelFor(model => model.Type, new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.Type, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.Type, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.CcNumber, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.CcNumber, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.CcNumber, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.CardFirstName, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.CardFirstName, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.CardFirstName, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.CardLastName, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.CardLastName, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.CardLastName, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.ExpirationDate, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.ExpirationDate, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.ExpirationDate, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.Cvc, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.Cvc, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.Cvc, "", new { @class = "text-danger" })
            </div>
        </div>

        <!-- TODO: This needs to be a dropdown -->
        <div class="form-group">
            @Html.LabelFor(model => model.AddressID, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.AddressID, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.AddressID, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <input type="submit" value="Save" class="btn btn-default" />
            </div>
        </div>
    </div>
}

<div>
    @Html.ActionLink("Back to List", "Index", "Account")
</div>

@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
}

2 个答案:

答案 0 :(得分:0)

在你的Html.BeginForm帮助器中,你需要在那些输入的控制器上添加参数,如下所示:

@model Models.MyModel

@using(Html.BeginForm("MyActionName","MyControllerName"))
{
    @Html.TextboxFor(m => m.ModelProperty)
    <!-- input button will send the form data to the server -->
    <input type="submit" value="Submit" />
}

并在您的控制器中:

public class MyControllerName:Controller
{
    public ActionResult MyActionName(MyModel model)
    {
        // add code here
    }
}

希望这有帮助。

答案 1 :(得分:0)

您的AddressID标准应为设置表。

public class CreditCard
{
    public int AddressID { get; set; }
}

发布表单时,默认模型绑定器将读取已发布的表单数据,并将值映射到CreditCart类对象的相应属性。如果您的属性不可设置,则模型绑定器无法将值设置为该属性。