Frage

Ich habe gerade angefangen, ViewModels zu verwenden. Könnt ihr diesen Code überprüfen, um zu sehen, ob ich den besten Praxis verfolge? Gibt es etwas Außergewöhnliches? Würden Sie die Validierung anders machen?

Entschuldigung, wenn Code langwierig ist (es gibt so viele Teile). Ich habe versucht, es so leicht wie möglich zu verstehen.

Vielen Dank!

Modell

  public class CustomerModel
  {
    [Required(ErrorMessage="Primer nombre!")]
    public string FirstName { get; set; }

    [Required(ErrorMessage="Segundo nombre!")]
    public string LastName { get; set; }

    [Required(ErrorMessage="Edad")]
    public int? Age { get; set; }

    public string State { get; set; }
    public string CountryID { get; set; }

    [Required(ErrorMessage="Phone Number")]
    public string PhoneNumber { get; set; }
  }

ViewModel

  public class CustomerViewModel
  {
    public CustomerModel Customer { get; set; }

    public string Phone1a { get; set; }
    public string Phone1b { get; set; }
    public string Phone1c { get; set; }
  }

Regler

    public ActionResult Index()
    {
      CustomerViewModel Customer = new CustomerViewModel()
      {
        Customer = new CustomerModel(),
      };


      return View(Customer);
    }


    [HttpPost]
    public ActionResult Index(CustomerViewModel c)
    {

      //ModelState.Add("Customer.PhoneNumber", ModelState["Phone1a"]);

      // Let's manually bind the phone number fields to the PhoneNumber properties in
      // Customer object. 
      c.Customer.PhoneNumber = c.Phone1a + c.Phone1b + c.Phone1c;

      // Let's check that it's not empty and that it's a valid phone number (logic not listed here)
      if (!String.IsNullOrEmpty(c.Customer.PhoneNumber))
      {
        // Let's remove the fact that there was an error! 
        ModelState["Customer.PhoneNumber"].Errors.Clear();
      } // Else keep the error there. 

      if (ModelState.IsValid)
      {
        Response.Write("<H1 style'background-color:white;color:black'>VALIDATED</H1>");
      }
      return View("Index", c);
    }

  }

Aussicht

@model MVVM1.Models.CustomerViewModel

@using (Html.BeginForm("Index", "Detail"))
{  
  <table border="1" cellpadding="1" cellspacing="1">
    <tr>
      <td>@Html.LabelFor(m => m.Customer.FirstName)</td>
      <td>
        @Html.TextBoxFor(m => m.Customer.FirstName)
        @Html.ValidationMessageFor(m => m.Customer.FirstName)
      </td>
    </tr>
    <tr>
      <td>@Html.LabelFor(m => m.Customer.LastName)</td>
      <td>
        @Html.TextBoxFor(m => m.Customer.LastName)
        @Html.ValidationMessageFor(m => m.Customer.LastName)
      </td>
    </tr>
    <tr>
      <td>@Html.LabelFor(m => m.Customer.Age)</td>
      <td>
        @Html.TextBoxFor(m => m.Customer.Age)
        @Html.ValidationMessageFor(m => m.Customer.Age)
      </td>
    </tr>

    <tr>
      <td>@Html.LabelFor(m => m.Customer.PhoneNumber)</td>
      <td width="350">
        @Html.TextBoxFor(m => m.Phone1a, new { size="4", maxlength="3" })
        @Html.TextBoxFor(m => m.Phone1b)
        @Html.TextBoxFor(m => m.Phone1c)
        <div>
        @Html.ValidationMessageFor(m => m.Customer.PhoneNumber)
        </div>
      </td>
    </tr>
    <tr>
      <td></td>
      <td>
        <input type="submit" value="Submit" /></td>
    </tr>
  </table>
}
War es hilfreich?

Lösung

Eine Sache, die auf mich herausspringt, ist Folgendes:

  if (ModelState.IsValid) 
  { 
    Response.Write("<H1 style'background-color:white;color:black'>VALIDATED</H1>"); 
  } 
  return View("Index", c); 

Denken Sie daran, dass Ansichtsmodelle gut für die Übergabe von Daten an Ihren Controller und zurück zu Ihrem Modell sind. Ich empfehle Ihnen, Ihrem Ansichtsmodell eine Isvalid -Eigenschaft hinzuzufügen und diese dann auf true zu setzen, anstatt die Antwort aufzurufen. Fügen Sie dies dann einfach an die Spitze Ihrer Teilansicht hinzu:

@if (Model.IsValid)
{
    <H1 style'background-color:white;color:black'>VALIDATED</H1>
}

Sie können auch aus Ihrer Sicht zu ModelState kommen, aber einige würden argumentieren, dass dies keine beste Praxis ist. Wenn Sie Ihrem Modell jedoch keine Eigenschaft für etwas hinzufügen möchten, das Sie nur in Ihrer Ansicht sehen können, können Sie dies einfach tun:

@if (ViewData.ModelState.IsValid)

Eine weitere nitpicky -Sache ist, dass MVC -Validierungsattribute sind Normalerweise verwendet zur Validierung auf der Benutzeroberfläche. Diese Validierung kann in anderen Bereichen wiederverwendet werden, in einigen Fällen jedoch suboptimal. Möglicherweise können Sie Ihre Domänenmodelle nicht immer ändern. Um meine gesamte UI -Validierung an einem Ort zu halten, wickle ich normalerweise meine Domain -Modelle in meinen Ansichtsmodellen ein, damit Sie so etwas erhalten:

public class CustomerViewModel                      
{                      
    public CustomerModel Customer { get; set; }

    [Required(ErrorMessage="Primer nombre!")]                        
    public string FirstName
    {
        get { return Customer.FirstName; } 
        set { Customer.FirstName = value; }
    }
...

Dies mag überflüssig erscheinen und nicht stets Die Mühe lohnt sich, aber es ist eine gute Praxis zu berücksichtigen, wenn die Modelle der Entity -Framework -Domänen oder andere Klassen verwendet werden, die schwierig oder unmöglich zu ändern sind.

Andere Tipps

Ich bekomme gerade selbst den Dreh an MVC, aber ich habe gestern dasselbe Thema recherchiert und zu dem Schluss gekommen, dass man kein Modellobjekt in das ViewModel aufnehmen sollte. Mein Verständnis ist also, dass es eine schlechte Praxis wäre, Ihr CustomerModel direkt in das CustomViewModel aufzunehmen.

Stattdessen möchten Sie jede der Eigenschaften von CustomerModel auflisten, die Sie in Ihr ViewModel aufnehmen möchten. Dann möchten Sie die Daten entweder manuell von CustomerModel auf das CustomViewModel abbilden oder ein Tool wie Automapper verwenden, das automatisch mit einer Codezeile wie dieser in Ihrer Aktionsmethode führt:

public ViewResult Example()
{
    // Populate/retrieve yourCustomer here
    Customer yourCustomer = new CustomerModel();

    var model = Mapper.Map<CustomerModel, CustomerViewModel>(yourCustomer);

    return View(model);
}

In diesem Fall gibt Mapper.map ein CustomViewModel zurück, das Sie an Ihre Ansicht übergeben können.

Sie müssen auch Folgendes in Ihre Anwendung_Start -Methode einbeziehen:

Mapper.CreateMap<CustomerModel, CustomerViewModel>();

Im Allgemeinen fand ich Automapper ziemlich einfach, sich an die Arbeit zu machen. Es ist automatisch, wenn die Feldnamen übereinstimmen. Wenn dies nicht der Fall ist oder Sie ein verschachteltes Objekt haben, können Sie diese Zuordnungen in der CreateMap -Zeile angeben. Wenn Ihr CustomerModel ein Adressobjekt anstelle von einzelnen Eigenschaften verwendet, würden Sie dies tun:

Mapper.CreateMap<CustomerModel, CustomerViewModel>()
    .ForMember(dest => dest.StreetAddress, opt => opt.MapFrom(src => src.Address.Street));

Bitte korrigiert mich jemand, wenn ich falsch liege, da ich mich nur mit MVC um den Kopf mache.

Ich würde sagen, Ihre ViewModel -Implementierung ist ziemlich Standard. Sie verwenden das ViewModel, um als Zwischenobjekt zwischen Ihrer Ansicht und Ihrem Domänenmodell zu fungieren. Welches ist eine gute Praxis.

Das einzige, worüber ich müde sein würde, ist, wie Sie mit Modellfehlern umgehen, und auch Ihr ViewModel sollte einige Attribute haben. Zum Beispiel möchten Sie möglicherweise die verwenden RegularExpressionAttribute Klasse:

  public class CustomerViewModel
  {
    public CustomerModel Customer { get; set; }

    [RegularExpression(@"^\d{3}$")]
    public string Phone1a { get; set; }
    [RegularExpression(@"^\d{3}$")]
    public string Phone1b { get; set; }
    [RegularExpression(@"^\d{4}$")]
    public string Phone1c { get; set; }
  }
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top