Suche…


Einführung

Die Modellbindung ist der Vorgang, bei dem HTTP-Parameter verwendet werden, normalerweise in der Abfragezeichenfolge einer GET-Anforderung oder im POST-Hauptteil, und diese auf ein Objekt anwenden, das dann objektorientiert überprüft und verwendet werden kann, ohne dass Controller-Aktionen erforderlich sind mit vertrauten Kenntnissen über das Abrufen von HTTP-Parametern.

Mit anderen Worten: Mit der Modellbindung können Aktionen in MVC über einen oder mehrere Parameter verfügen, unabhängig davon, ob es sich um einen Werttyp oder ein Objekt handelt.

Bemerkungen

Um zu versuchen, eine Instanz in der Aktion zu erstellen, durchsucht der Bindungsmodellprozess Daten an verschiedenen Stellen:

  • Formulardaten
  • Routendaten
  • Abfragezeichenfolge
  • Files Custom (Cookies zum Beispiel)

Routenwertbindung

Wenn Sie einige Standardrouten wie {controller=Home}/{action=Index}/{id?} Angegeben haben, wenn Sie die URL https://stackoverflow.com/questions/1558902

Dies würde an den QuestionsController gehen und der Wert 1558902 würde einem id-Parameter einer Indexaktion zugeordnet werden, dh

public ActionResult Index(int? id){
     //id would be bound to id of the route
}

Abfrage-String-Bindung

Um die Routenbindung zu erweitern, sagen Sie, Sie hätten eine URL wie https://stackoverflow.com/questions/1558902?sort=desc

und Routing wie {controller=Home}/{action=Index}/{id?}

public ActionResult Index(int? id, string sort){
     //sort would bind to the value in the query string, i.e. "desc"
}

An Objekte binden

Häufig arbeiten Sie mit Ansichtsmodellklassen in asp.net-mvc und möchten Eigenschaften an diese binden. Dies funktioniert ähnlich wie bei der Zuordnung zu einzelnen Parametern.

Angenommen, Sie hatten ein einfaches Ansichtsmodell für ein PostViewModel wie dieses

public class PostViewModel{
  public int Id {get;set;}
  public int SnappyTitle {get;set;}
}

Dann hatten Sie die Werte für Id und SnappyTitle aus einem Formular in der http-Anfrage gepostet und dann direkt auf dieses Modell abgebildet, wenn das Modell selbst der Aktionsparameter war, z

public ActionResult UpdatePost(PostViewModel viewModel){
  //viewModel.Id would have our posted value
}

Beachten Sie, dass bei der Bindung die Parameter- und Eigenschaftsnamen nicht berücksichtigt werden. Wenn möglich, werden auch Werte ausgegeben. Ich lasse mehr Randfälle für spezifische Beispiele

Ajax-Bindung

Dies sind Formularwerte, die in der HTTP-Anforderung mit der POST-Methode gespeichert werden. (einschließlich jQuery-POST-Anforderungen).

Angenommen, Sie haben einen Ajax-Beitrag gemacht

$.ajax({
    type: 'POST',
    url: window.updatePost,
    data:  { id: 21, title: 'snappy title' },
    //kept short for clarity
});

Hier wären die beiden Werte in json, id und title, an die passende Aktion gebunden, z

public JsonResult UpdatePost(int id, string title) {
    ...
}

Allgemeine, sitzungsbasierte Modellbindung

Manchmal müssen wir das gesamte Modell beibehalten und auf Aktionen oder sogar Controller übertragen. Speichern des Modells bei Sitzung Gute Lösung für diese Art von Anforderungen. Wenn wir dies mit den leistungsstarken Modellbindungsfunktionen von MVC kombinieren, erhalten Sie eine elegante Methode. Wir können eine generische, sitzungsbasierte Modellbindung in drei einfachen Schritten erstellen:

Schritt 1: Erstellen Sie einen Modellordner

Erstellen Sie selbst einen Modellordner. Ich persönlich habe die SessionDataModelBinder- Klasse im Ordner / Infrastructure / ModelBinders erstellt .

using System;
using System.Web.Mvc;

public class SessionDataModelBinder<TModel>
    : IModelBinder
    where TModel : class
{
    private string SessionKey { get; set; }

    public SessionDataModelBinder(string sessionKey)
    {
        if (string.IsNullOrEmpty(sessionKey))
            throw new ArgumentNullException(nameof(sessionKey));
        SessionKey = sessionKey;
    }

    public object BindModel(
        ControllerContext controllerContext, 
        ModelBindingContext bindingContext)
    {
        // Get model from session
        TModel model = controllerContext
            .HttpContext
            .Session[SessionKey] as TModel;
        // Create model if it wasn't found from session and store it
        if (model == null)
        {
            model = Activator.CreateInstance<TModel>();
            controllerContext.HttpContext.Session[SessionKey] = model;
        }
        // Return the model
        return model;
    }
}

Schritt zwei: Registrieren Sie den Ordner

Wenn wir modell wie unten haben:

public class ReportInfo
{
    public int ReportId { get; set; }
    public ReportTypes TypeId { get; set; }
}

public enum ReportTypes
{
    NotSpecified,
    Monthly, Yearly
}

Wir können einen sitzungsbasierten Modellbinder für dieses Modell in Global.asax in der Application_Start- Methode registrieren:

protected void Application_Start()
{
    .........

    // Model binders.
    // Remember to specy unique SessionKey
    ModelBinders.Binders.Add(typeof(ReportInfo), 
        new SessionDataModelBinder<ReportInfo>("ReportInfo"));
}

Schritt drei: Verwenden Sie es!

Jetzt können wir von diesem Modellordner profitieren, indem wir unseren Aktionen Parameter hinzufügen :

public class HomeController : Controller
{
    public ActionResult Index(ReportInfo reportInfo)
    {
        // Simply set properties
        reportInfo.TypeId = ReportTypes.Monthly;

        return View();
    }

    public ActionResult About(ReportInfo reportInfo)
    {
        // reportInfo.TypeId is Monthly now because we set
        // it previously in Index action.
        ReportTypes currentReportType = reportInfo.TypeId;

        return View();
    }
}

Bindung an PostModel verhindern

Betrachten eines (Post-) Modells:

public class User
{
    public string FirstName { get; set; }
    public bool IsAdmin { get; set; }
}

Mit einer Ansicht wie so:

@using (Html.BeginForm()) {
    @Html.EditorFor(model => model.FirstName)
    <input type="submit" value="Save" />       
}

Um zu verhindern, dass ein böswilliger Benutzer IsAdmin zuweist, können Sie das Bind Attribut in der Aktion verwenden:

[HttpPost]
public ViewResult Edit([Bind(Exclude = "IsAdmin")] User user)
{
    // ...
}

Datei-Upload

Modell:

public class SampleViewModel
{
    public HttpPostedFileBase file {get;set;}
}

Aussicht:

@model HelloWorldMvcApp.SampleViewModel

@using (Html.BeginForm("Index","Home",FormMethod.Post, new { enctype = "multipart/form-data" }))
{
    <div class="form-group">
        @Html.TextBoxFor(model => model.file, new {@class="form-control", type="file"}) 
        @Html.ValidationMessageFor(model => model.file)
    </div>

    <button type="submit" class="btn btn-success submit">Upload</button>
}

Aktion:

[HttpPost]
public ActionResult Index(SampleViewModel model)
{                
    
    if (model.file.ContentLength > 0) 
    {
        string fileName = Path.GetFileName(model.file.FileName);
        string fileLocation = "~/App_Data/uploads/"+ fileName;
        model.file.SaveAs(Server.MapPath(fileLocation));
    }
    return View(model);
}

Datumsfelder manuell mit dynamischen Formaten mithilfe des Modellbinders überprüfen

Wenn verschiedene Benutzer ein anderes datetime-Format benötigen, müssen Sie möglicherweise die eingehende Datumszeichenfolge entsprechend dem Format bis zum tatsächlichen Datum analysieren. In diesem Fall kann Ihnen dieses Snippet helfen.

public class DateTimeBinder : DefaultModelBinder 
{
    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {

                var value = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
                DateTime date;
                var displayFormat = Session["DateTimeFormat"];
                if (value.AttemptedValue != "")
                {
                    if (DateTime.TryParseExact(value.AttemptedValue, displayFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out date))
                    {
                        return date;
                    }
                    else
                    {
                        bindingContext.ModelState.AddModelError(bindingContext.ModelName, "Invalid date format");
                    }
                }
            }

        return base.BindModel(controllerContext, bindingContext);
    }


Modified text is an extract of the original Stack Overflow Documentation
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow