ASP C#模型绑定验证

时间:2018-10-28 11:39:49

标签: c# asp.net model-view-controller

我正在尝试使用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");
            }

        }
    }
}

1 个答案:

答案 0 :(得分:0)

我建议控制者应该简单并做出简单的决定。这是来自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不为null,则_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>

对于我的模型,因为这是一个小类,所以我直接使用实体框架,并使用局部类对其进行扩展。对于更大或更复杂的数据,我建议使用单独的视图模型,从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; }
}