我正在尝试使用c#mvc验证表单,我已经设置了验证模型。
我添加了模型绑定器来连接表单中的请求,然后将其发送到提交控制器进行验证。
当if语句检查对象绑定器是否正确时,它会将代码视为有效。关于使用服务器端验证检查表单中的信息我做错了什么的任何想法?
模型:
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Web;
namespace messageBoard.Models
{
public class Messages
{
[Required]
[StringLength(250)]
public string Sender { get; set; }
[Required]
public string Receiver { get; set; }
public int Year { get; set; }
public string Form { get; set; }
[Required]
public DateTime StartDate { get; set; }
[Required]
public DateTime Expiry { get; set; }
[Required]
[StringLength(250)]
public string Title { get; set; }
[Required]
public string Message { get; set; }
}
}
控制器:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using messageBoard.Models;
namespace messageBoard.Controllers
{
public class Messagebinder : IModelBinder
{
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
HttpContextBase objContext = controllerContext.HttpContext;
string sender = objContext.Request.Form["txtSender"];
string reciever = objContext.Request.Form["txtReciever"];
string form = objContext.Request.Form["txtForm"];
string strYear = objContext.Request.Form["txtYear"];
Int32 year = Int32.Parse(strYear);
string strStart = objContext.Request.Form["txtStartDate"];
DateTime startParse = DateTime.Parse(strStart);
string strExpiry = objContext.Request.Form["txtExpiry"];
DateTime expiryParse = DateTime.Parse(strExpiry);
string title = objContext.Request.Form["txtTitle"];
string message = objContext.Request.Form["txtMessage"];
Messages obj = new Messages()
{
Sender = sender,
Receiver = reciever,
Form = form,
Year = year,
StartDate = startParse,
Expiry = expiryParse,
Title = title,
Message = message
};
return obj;
}
}
public class MessagesController : Controller
{
// GET: Messages
public ActionResult Load()
{
Messages obj = new Messages {
Sender = "Ross McKenzie",
Receiver = "Noah McKenzie",
Year = 8,
Form ="8NM",
StartDate = new DateTime(2018, 10, 22),
Expiry = new DateTime(2018, 10, 31),
Title = "Noah",
Message = "This is the first message for the test of the internal message board, oh and I love you Noah"
};
return View("Messages",obj);
}
public ActionResult Enter()
{
return View("EnterMessages",new Messages());
}
public ActionResult Submit([ModelBinder(typeof(Messagebinder))] Messages obj)
{
if(ModelState.IsValid)
{
return View("Messages", obj);
}
else
{
return View("EnterMessages");
}
}
}
}
我建议控制器应该简单并做出简单的决定。这是ASP.NET MVC 5中的一个
首先,我使用依赖注入将业务服务接口引入构造函数。我还使用了所有控制器公共代码所在的基类,所以我将业务接口传递给了这个仍然可以从这个类引用的接口。您需要阅读IoC以及如何实现它。微软有一个我使用的简单,但还有其他人。
public SparesSectionsController(IBusinessService bs) : base(bs)
{
}
对于CRUD操作,我有一对操作以及一个列出CREATE,EDIT,DELETE记录的索引。这是一个用于编辑现有记录的
[HttpGet]
public async Task<ActionResult> Edit(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
SparesSection sparesSection = await _bs.SparesSection_GetAsync(id.Value);
if (sparesSection == null)
{
return HttpNotFound();
}
return View(sparesSection);
}
相应的POST操作将任何必填字段绑定为操作参数的一部分。
为简单起见,但可能是不好的做法,我将模型状态传递给业务层,以便可以添加任何其他字段或一般错误。最好在较低级别定义的单独类中定义返回业务层错误,并将这些错误添加到模型状态中。后一种方法打破了对MVC的依赖,并使业务层抽象化,以用作Web界面或其他独立业务源。
请注意,ViewMessage是一个基类属性,只是将一些文本放入TempData属性中。然后,_Layout会在视图中显示该消息时显示该消息。这种方法允许在重定向期间跨行动持久化,而ViewBag则不然
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Edit([Bind(Include = "SparesSectionId,SparesSectionTitle")] SparesSection sparesSection)
{
if (ModelState.IsValid)
{
await _bs.SparesSection_UpdateAsync(sparesSection, ModelState);
if (ModelState.IsValid)
{
ViewMessage = "Saved " + sparesSection.SparesSectionTitle;
return RedirectToAction("Index");
}
}
return View(sparesSection);
}
视图轻巧紧凑
@model YourProjectName.Models.SparesSection
@{
ViewBag.Title = "Edit Spares Section";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<div class="container w-50">
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
<div class="form-horizontal">
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
@Html.HiddenFor(model => model.SparesSectionId)
<div class="form-group">
@Html.LabelFor(model => model.SparesSectionTitle, htmlAttributes: new { @class = "control-label" })
@Html.EditorFor(model => model.SparesSectionTitle, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.SparesSectionTitle, "", new { @class = "text-danger" })
</div>
<div class="d-flex">
<div class="ml-auto">
<input type="submit" value="Save" class="btn btn-primary btn-sm btn-default" />
</div>
</div>
</div>
}
</div>
至于我的模型,因为这是一个小类,我直接使用Entity Framework并使用partial类扩展它。对于更大或更复杂的数据,我建议使用单独的视图模型,您可以从EF数据中获取一个获取的视图模型以及任何其他资源
//-----------------------------------------------------------------------
#region Spares Section
[MetadataType(typeof(SparesSectionMetaData))]
public partial class SparesSection { }
public class SparesSectionMetaData
{
[ScaffoldColumn(false)]
[DefaultValue(0)]
[Required]
public int SparesSectionId { get; set; }
[DisplayName("Spares Section Title")]
[StringLength(100, MinimumLength = 2, ErrorMessage = "2-100 characters")]
[Required]
public string SparesSectionTitle { get; set; }
}