我正在使用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")
}
答案 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
类对象的相应属性。如果您的属性不可设置,则模型绑定器无法将值设置为该属性。