2013-01-13 27 views
1

我目前經歷的MVC教程書呆子晚餐使用MVS 2010我已經起身到第7步,但我剛纔注意到,當我現在去造屏,這是不完全正確。MVC書呆子晚餐CreateView的不顯示EVENTDATE

  1. 標題輸入框似乎包含ViewBag.Title而不是作爲空白。
  2. EventDate輸入框爲空時,它應該從現在起被自動設置爲7天。

我不記得它是這樣的教程早些時候。

下面是從DinnersController.cs中的這段,處理創建:

// 
    // 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)); 
    } 

這裏是查看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

任何人都知道WH我失蹤了?

編輯 - 添加了晚餐型號

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

您應該使用@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語句。如果在ID,用於在HTML源的實際晚餐對象的屬性仔細觀察,你會發現它們都呈現爲「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實現時,您會發現其他方式以較爲冗長的方式完成相同的任務。堅持下去!

+0

對於視圖中的所有TextBox和ValidationMessage實例是否相同? –

+0

是的,你明白了!我剛剛更新了一些更詳細的答案,但是,一般來說,你應該使用@ Html。*對於幫助者處理強類型視圖 – Tommy

+0

好吧,這似乎解決了原來的問題,但現在我已經取代了所有'@ Html.TextBox()用於'@ Html.TextBoxFor',同樣用於'@ Html.ValidationMessage'在處理錯誤時不再將紅色astrix應用於輸入框或紅色hi-light到輸入框iteself,儘管它仍然在頁面頂部顯示錯誤。 –

相關問題