MVC书呆子晚餐CreateView没有显示EventDate

时间:2013-01-13 17:52:51

标签: asp.net-mvc-3 nerddinner

我目前正在阅读使用MVS 2010的MVC教程Nerd Dinner我已经到了第7步但我刚刚注意到,当我现在进入创建屏幕时,它不太正确。

  1. 标题输入框似乎包含ViewBag.Title而不是空白。
  2. EventDate输入框为空白,应自动设置为7天后。
  3. 我不记得之前在教程中是这样的。

    以下是DinnersController.cs处理Create:

    的snippit
        //
        // GET: /Dinners/Create
    
        public ActionResult Create()
        {
            Dinner dinner = new Dinner()
            {
                EventDate = DateTime.Now.AddDays(7)
            };
    
            return View(new DinnerFormViewModel(dinner));
        }
    
        //
        // POST: /Dinners/Create
    
        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult Create(Dinner dinner)
        {
            if (ModelState.IsValid)
            {
                try
                {
                    dinner.HostedBy = "SomeUser";
    
                    dinnerRepository.Add(dinner);
                    dinnerRepository.Save();
    
                    return RedirectToAction("Details", new { id = dinner.DinnerID });
                }
                catch
                {
                    ModelState.AddModelErrors(dinner.GetRuleViolations());
                }
    
            }
    
            return View(new DinnerFormViewModel(dinner));
        }
    

    这是View Create.cshtml

    @model NerdDinner.Models.DinnerFormViewModel
    
    @{
        ViewBag.Title = "Host a Dinner";
    }
    
    <h2>Host a Dinner</h2>
    
    @Html.ValidationSummary("Please correct the errors and try again")
    
    @using (Html.BeginForm()) {
    
        <fieldset>
            <p>
                @Html.LabelFor(model => Model.Dinner.Title)
                <br />
                @Html.TextBox("Title")
                @Html.ValidationMessage("Title", "*")
            </p>
            <p>
                @Html.LabelFor(model => Model.Dinner.EventDate)
                <br />
                @Html.TextBox("EventDate")
                @Html.ValidationMessage("EventDate", "*")
            </p>
            <p>
                @Html.LabelFor(model => Model.Dinner.Description)
                <br />
                @Html.TextArea("Description")
                @Html.ValidationMessage("Description", "*")
            </p>
            <p>
                @Html.LabelFor(model => Model.Dinner.Address)
                <br />
                @Html.TextBox("Address")
                @Html.ValidationMessage("Address", "*")
            </p>
            <p>
                @Html.LabelFor(model => Model.Countries)
                <br />
                @Html.DropDownList("Country", Model.Countries)
                @Html.ValidationMessage("Country", "*")
            </p>
            <p>
                @Html.LabelFor(model => Model.Dinner.ContactPhone)
                <br />
                @Html.TextBox("ContactPhone")
                @Html.ValidationMessage("ContactPhone", "*")
            </p>
            <p>
                @Html.LabelFor(model => Model.Dinner.Latitude)
                <br />
                @Html.TextBox("Latitude")
                @Html.ValidationMessage("Latitude", "*")
            </p>
            <p>
                <label for="Longitude">Longitude:</label>
                <br />
                @Html.TextBox("Longitude")
                @Html.ValidationMessage("Longitude", "*")
            </p>
            <p>
                <input type="submit" value="Create" />
            </p>
        </fieldset>
    }
    
    <div>
        @Html.ActionLink("Back to List", "Index")
    </div>
    

    最后这是浏览器中的输出:

    output

    任何人都知道我缺少什么?

    编辑 - 添加晚餐模型

    using System;
    using System.Collections.Generic;
    using System.Data.Linq;
    using System.Linq;
    using System.Web;
    using System.Web.Mvc;
    using System.Text; //added this - not in tut
    using System.Text.RegularExpressions; //added this - not in tut
    
    namespace NerdDinner.Models
    {
        [Bind(Include = "Title,Description,EventDate,Address,Country,ContactPhone,Latitude,Longitude")]
        public partial class Dinner
        {
    
            public bool IsValid
            {
                get { return (GetRuleViolations().Count() == 0); }
            }
    
            public IEnumerable<RuleViolation> GetRuleViolations()
            {
                if (String.IsNullOrEmpty(Title))
                    yield return new RuleViolation("Title required", "Title");
    
                if (String.IsNullOrEmpty(Description))
                    yield return new RuleViolation("Description required", "Description");
    
                if (String.IsNullOrEmpty(HostedBy))
                    yield return new RuleViolation("HostedBy required", "HostedBy");
    
                if (String.IsNullOrEmpty(Address))
                    yield return new RuleViolation("Address required", "Address");
    
                if (String.IsNullOrEmpty(Country))
                    yield return new RuleViolation("Country required", "Country");
    
                if (String.IsNullOrEmpty(ContactPhone))
                {
                    yield return new RuleViolation("ContactPhone required", "ContactPhone");
                }
                else
                {
                    if (!PhoneValidator.IsValidNumber(ContactPhone, Country))
                        yield return new RuleViolation("Phone# does not match country", "ContactPhone");
                }
    
    
                    yield break;
            }
    
            partial void OnValidate(ChangeAction action)
            {
                if (!IsValid)
                    throw new ApplicationException("Rule voilations prevent saving");
            }
    
        }
    
        public class RuleViolation
        {
            public string ErrorMessage { get; private set; }
            public string PropertyName { get; private set; }
    
            public RuleViolation(string errorMessage, string propertyName)
            {
                ErrorMessage = errorMessage;
                PropertyName = propertyName;
            }
        }
    
        public class PhoneValidator
        {
            static IDictionary<string, Regex> countryRegex = new Dictionary<string, Regex>()
            {
                { "USA", new Regex("^[2-9]\\d{2}-\\d{3}-\\d{4}$")},
                { "UK", new Regex("(^1300\\d{6}$)|(^1800|1900|1902\\d{6}$)|(^0[2|3|7|8]{1}[0-9]{8}$)|(^04\\decimal{2,3}\\decimal{6}$)")},
                { "Netherlands", new Regex("(^\\+[0-9]{2}|^\\+[0-9]{2}\\(0\\)|^\\(\\+[0-9]{2}\\)\\(0\\)|^00[0-9]{2}|^0)([0-9]{9}$|[0-9\\-\\s]{10}$)")},
    
            };
    
            public static bool IsValidNumber(string phoneNumber, string country)
            {
                if (country != null && countryRegex.ContainsKey(country))
                    return countryRegex[country].IsMatch(phoneNumber);
                else
                    return false;
            }
    
            public static IEnumerable<string> Countries
            {
                get
                {
                    return countryRegex.Keys;
                }
            }
        }
    
        public class DinnerFormViewModel
        {
    
            // Properties
            public Dinner Dinner { get; private set; }
            public SelectList Countries { get; private set; }
    
            // Contructor
            public DinnerFormViewModel(Dinner dinner)
            {
                Dinner = dinner;
                Countries = new SelectList(PhoneValidator.Countries, dinner.Country);
            }
        }
    }
    

1 个答案:

答案 0 :(得分:1)

您应该使用@Html.TextboxFor代替@Html.Textbox

<p>
            @Html.LabelFor(model => Model.Dinner.EventDate)
            <br />
            @Html.TextBoxFor(model => Model.Dinner.EventDate)
            @Html.ValidationMessageFor(model => Model.Dinner.EventDate)
        </p>

基本@Html.Textbox将呈现一个文本框,其中包含您传递的字符串中指定的name属性。 MVC将调查ViewBag以查看是否有任何带有该键的项目来填充文本框(这就是您的Title属性使用视图顶部的页面标题的原因),但是没有将视图输入绑定到实际模型或随模型一起发送的任何预先填充的数据。通过使用TextBoxFor(或labelFor等),这将输入绑定到实际的模型属性。这也是DataAnnotations应用于表单的方式。我最后一句话的意思是这个。我们假设这是你模型的一部分

public class DinnerViewModel{
  [DisplayName("Dinner Location")]
  [Required(ErrorMessage="You must specify a location")]
  public string Location {get;set;}
}

在您的视图中,您可以使用@Html呈现所需的部分。*对于方法(就像您的标签一样)

<p>
   @Html.LabelFor(model => Model.Location )
   <br />
   @Html.TextBoxFor(model => Model.Location)
   @Html.ValidationMessageFor(model => Model.Location )
</p>

应该像这样呈现一些HTML(不包括错误消息)

<p>
  <label for="Location">Dinner Location</label>
  <br/>
  <input type="text" name="Location" id="Location"/>
  *the validation related stuff*
</p>

<强>附录

为了使您的验证能够使用您正在使用的方法,您必须稍微更改yield return语句。如果仔细查看HTML源代码中实际晚餐对象属性的ID,您会看到它们呈现为“Dinner.Title”或“Dinner.Description”。这是因为它们是如何存储在您的模型中的(请记住使用model => Model.Dinner.EventDate?)这将呈现ID为“Dinner.EventDate”的元素。

鉴于此,您需要更新从模型的RuleViolation部分返回的字符串:

public IEnumerable<RuleViolation> GetRuleViolations()
        {
            if (String.IsNullOrEmpty(Title))
                yield return new RuleViolation("Title required", "Dinner.Title");

            if (String.IsNullOrEmpty(Description))
                yield return new RuleViolation("Description required", "Dinner.Description");

            if (String.IsNullOrEmpty(HostedBy))
                yield return new RuleViolation("HostedBy required", "Dinner.HostedBy");

            if (String.IsNullOrEmpty(Address))
                yield return new RuleViolation("Address required", "Dinner.Address");

            if (String.IsNullOrEmpty(Country))
                yield return new RuleViolation("Country required", "Country");

            if (String.IsNullOrEmpty(ContactPhone))
            {
                yield return new RuleViolation("ContactPhone required", "Dinner.ContactPhone");
            }
            else
            {
                if (!PhoneValidator.IsValidNumber(ContactPhone, Country))
                    yield return new RuleViolation("Phone# does not match country", "Dinner.ContactPhone");
            }


                yield break;
        }

现在,您的RuleViolations将与实际输入ID匹配,所有内容都将再次闪亮和棒极了。这似乎有点工作,但是因为你正在完成一个教程,我不想过多地推动你的方式。但是,当您探索.NET MVC实现时,您将找到以更简洁的方式完成相同任务的其他方法。坚持下去!