Frage

Hintergrund:In meinen MVC -Post -Back -Methoden erhalte ich Befehl Objekte anstelle von Modellen. Die Idee ist, dass diese Befehlsobjekte (die in etwa gleichbedeutend mit Transaktionskripten gleichsetzen) eingerichtet und bereit werden, bei Eingabe der Aktionsmethode auszuführen, wobei der Modellbindemittel Parameter festgelegt hat, die während des Ausführungsprozesses verwendet werden:

public class MyCommand : IMyCommand
{
    // In this case Value1 and Value2 are being set by the default model binder from posted form values - wonderful :)
    public String Value1 { get; set; }
    public String Value2 { get; set; }

    public CommandResult ExecuteCommand()
    {
        // Does something awesome...
    }
}

Um die Dinge etwas komplexer zu machen, haben meine Befehlsobjekte Abhängigkeiten (Dienste, Repositorys usw.), die in ihren jeweiligen Konstruktoren erforderlich sind. Daher musste ich einen benutzerdefinierten Modellbindemittel erstellen, der den Standard -Abhängigkeits -Lolver (der bereits mit meinem IOC -Container eingerichtet wurde) verwendete, um die Modellobjekte zu konstruieren:

public class DependencyModelBinder : DefaultModelBinder
{
    protected override Object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType)
    {
        return DependencyResolver.Current.GetService(modelType);
    }
}

Und einrichten in Global.asax.cs Like SO:

ModelBinders.Binders.DefaultBinder = new DependencyModelBinder();

Auch dies alles funktioniert einwandfrei, die Abhängigkeiten werden in den Konstruktor injiziert, und dann übernimmt der Standardmodellbindemittel die Eigenschaften wie gewohnt.

Die Angelegenheit:Das Problem, das ich habe, ist, dass alle meine Befehlsobjekte einen "SessionID" -Roid -Parameter (der aus einem Cookie stammt) haben, und das erste, was sie tun, ist, ein Sitzungsobjekt aus dieser ID mithilfe eines injizierten Dienstes zu beheben.

public class MyCommand : IMyCommand
{
    public MyCommand (ISessionRepository sessionRepository) { ... }

    public Guid SessionId { get; set; } // Set by model binder from a cookie...

    public CommandResult Execute()
    {
        Session session = SessionRepository.Get(SessionId);

        if (session == null)
            // Do something not so awesome...
    }
}

Ich wollte diese Wiederholung entfernen, also habe ich einen zweiten Modellbindemittel erstellt, der diese Suche im Repository kümmerte, was bedeutet, dass meine Befehlsobjekte eine haben könnten Session Eigenschaft direkt (Entfernen der Konstruktorabhängigkeit für das Sitzungsrepository).

public class SessionModelBinder : DefaultModelBinder
{
    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        var sessionRepository = DependencyResolver.Current.GetService<ISessionRepository>();

        return sessionRepository.Get((Guid)controllerContext.HttpContext.Request["SessionId"]);
    }
}

Mein Global.asax.cs Datei jetzt so aussieht wie so:

ModelBinders.Binders.DefaultBinder = new DependencyModelBinder();
ModelBinders.Binders.Add(typeof(Session), new SessionModelBinder());

Nachdem ich den SessionModelBinder isoliert getestet habe, weiß ich, dass er funktioniert. Wenn es jedoch in Verbindung mit dem Abhängigkeitsmodelbinder verwendet wird, wird es nie aufgerufen. Wie kann ich MVC dazu bringen, meinen DependentyModelBinder beim Erstellen von Modellobjekten zu verwenden, aber wenn ich meinen SessionModelBinder bei der Bindung von Sitzungseigenschaften auf ihnen verwendete? Oder kennt jemand einen besseren Ansatz dafür?

War es hilfreich?

Lösung

Sie können die GetPropertyValue -Methode in Ihrem ursprünglichen Modellbinder verwenden, um einen Wert für die Sitzungseigenschaft bereitzustellen:

public class DependencyModelBinder : DefaultModelBinder
{
    protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType)
    {
        return DependencyResolver.Current.GetService(modelType);
    }

    protected override object GetPropertyValue(ControllerContext controllerContext, ModelBindingContext bindingContext, PropertyDescriptor propertyDescriptor, IModelBinder propertyBinder)
    {
        if (propertyDescriptor.Name == "Session")
        {
            var sessionRepository = DependencyResolver.Current.GetService<ISessionRepository>();
            return sessionRepository.Get(controllerContext.HttpContext.Request["SessionId"]);
        }
        return base.GetPropertyValue(controllerContext, bindingContext, propertyDescriptor, propertyBinder);
    }
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top