9 Stimmen

ASP.NET MVC Modellbindung und Validierung Frage

Ich versuche, MVC für ein neues Projekt zu verwenden, nachdem ich mit all den Beispielen und Tutorials und so um den Block gegangen bin. Allerdings habe ich eine harte Zeit herauszufinden, wo bestimmte Dinge stattfinden sollte.

Ich habe zum Beispiel eine Entität namens Profil. Diese Entität enthält den normalen Profiltyp zusammen mit einer DateOfBirth-Eigenschaft vom Typ DateTime. Auf dem HTML-Formular ist das Feld für das Geburtsdatum in 3 Felder aufgeteilt. Ich weiß, dass ich einen benutzerdefinierten Modellbinder verwenden kann, um dies zu behandeln, aber was ist, wenn das eingegebene Datum kein gültiges Datum ist? Sollte ich das im Model Binder überprüfen? Sollte die gesamte Validierung im Modellbinder stattfinden? Ist es in Ordnung, nur ein paar Dinge im Model Binder zu validieren und den Rest im Controller oder dem Modell selbst?

Hier ist der Code, den ich jetzt habe, aber er sieht für mich einfach nicht richtig aus. Sieht schmutzig oder stinkend aus.

namespace WebSite.Models
{
    public class ProfileModelBinder : IModelBinder
    {
        public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
        {
            DateTime birthDate;

            var form = controllerContext.HttpContext.Request.Form;
            var state = controllerContext.Controller.ViewData.ModelState;

            var profile = new Profile();
            profile.FirstName = form["FirstName"];
            profile.LastName = form["LastName"];
            profile.Address = form["Address"];
            profile.Address2 = form["Address2"];
            profile.City = form["City"];
            profile.State = form["State"];
            profile.Zip = form["Zip"];
            profile.Phone = form["Phone"];
            profile.Email = form["Email"];
            profile.Created = DateTime.UtcNow;
            profile.IpAddress = controllerContext.HttpContext.Request.UserHostAddress;

            var dateTemp = string.Format("{0}/{1}/{2}",
                form["BirthMonth"], form["BirthDay"], form["BirthYear"]);

            if (string.IsNullOrEmpty(dateTemp))
                state.AddModelError("BirthDate", "Required");
            else if (!DateTime.TryParse(dateTemp, out birthDate))
                state.AddModelError("BirthDate", "Invalid");
            else
                profile.BirthDate = birthDate;

            return profile;
        }        
    }
}

Aufbauend auf dem Beispielcode oben, wie würden Sie die Validierung Nachricht für ein 3-Teil-Feld tun? Im obigen Fall verwende ich einen völlig separaten Schlüssel, der nicht wirklich einem Feld im Formular entspricht, weil ich nicht möchte, dass eine Fehlermeldung neben allen 3 Feldern erscheint. Ich möchte, dass sie nur rechts neben dem Feld "Jahr" erscheint.

0 Stimmen

Sind Sie auf der Suche nach einer Modellvalidierung oder einer Formularvalidierung? Ich würde beides empfehlen. Auf diese Weise können Sie moq das Modell als auch eine reiche UI auf dem Frontend bieten.

0voto

bkwdesign Punkte 1583

Ich war es leid, kleine ViewModels für kleine Zwecke zu erstellen, die nur Teile meines kilometerlangen Domänenmodells berührten.

Deshalb habe ich mir eine eigene Methode ausgedacht, um dieses Problem zu lösen. Mein ViewModel ist ein typeOf DomainModel, und ich verwende eine Custom Model Binder um sicherzustellen, dass die Identitätseigenschaften zuerst geladen werden - sobald die Identität festgelegt ist, wird ein DomainModel.Load ausgelöst, und der Rest der Bindungsaktivität führt im Wesentlichen eine "Zusammenführung" durch.

Wieder, wenn mein ViewModel gebunden ist (z. B. auf ein Formular POST), nach wesentlichen Felder, die die ID festgelegt sind - es lädt sofort das Domänenmodell aus der Datenbank. Ich musste mir einfach einen Ersatz für den DefaultModelBinder einfallen lassen. Mein benutzerdefinierter Modellbinder hier auf StackOverflow gepostet können Sie die Bindungsreihenfolge der Eigenschaften steuern.

Sobald ich garantieren kann, dass Identitätseigenschaften gebunden sind (die Interna meines Viewmodells warten auf die Fertigstellung von Identitätssetzern), löse ich ein Laden meines Domänenmodells aus, während der Rest der Eigenschaften gebunden wird, d.h. sie werden in das geladene Domänenmodell "verschmolzen".

Grundsätzlich kann ich alle meine verschiedenen Razor-Ansichten haben, ob sie 5 Formularfelder oder 50 Felder des Modells alle übermitteln an einen Controller-Aktion, die wie folgt aussieht (zugegeben, ich mache noch separate Aktionen, wo benötigt, um entsprechende benutzerdefinierte Business-Sachen zu tun aber der Punkt ist, meine Controller-Aktionen sind konzentriert und prägnant)

<HttpPost()>
<Authorize(Roles:="MYCOMPANY\activeDirRoleForEditing")>
Function Edit(<Http.FromBody()> ByVal mergedModel As OrderModel) As ActionResult
    'notice: NO loading logic here - it already happened during model binding
    'just do the right thing based upon resulting model state
    If Me.ModelState.IsValid Then

        mergedModel.SaveAndReload("MyServiceWebConfigKey")

        ViewBag.SuccessMessage = String.Format("You have successfully edited the order {0}", mergedModel.Id)

        Return View("Edit", mergedModel)
    Else
        ViewBag.ErrorText = String.Format("Order {0} not saved. Check for errors and correct.", mergedModel.Id)
        Return View("Edit", mergedModel)
    End If
End Function

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X