2016-09-28 3 views
0

Ich bin wirklich neu in ASP.NET MVC und im Grunde alles Web bezogen. Sorry, wenn dies nooby ist, aber ich versuche, dies zu tun:Bind ViewModel -Eigenschaft von Teilansicht zu Hauptansicht

Ich habe ein Ansichtsmodell mit einer komplexen Objekt (Navigation hier):

public class Request 
{ 
    public virtual BaseRequestData RequestData { get; set; } 
} 

BaseRequestData abstrakt ist, aber ein paar Klassen von ihm geerbt, die haben andere Attribute wie diese:

public class AcceleratorRequestData : BaseRequestData 
{ 
    [Display(Name="Downside amount")] 
    [Range(-100,0,ErrorMessage = "Downside participation must be between 0 and -100")] 
    [Required] 
    public decimal PutNotional { get; set; } 

    [Display(Name="Upside strike")] 
    [Range(1, 2, ErrorMessage = "Upside strike must be between 100% and 200%")] 
    public decimal CallPercentStrike { get; set; } 

} 

auf meinem Haupt ‚erstellen‘ Ansicht, die ich auf meine Anfrage Modell binden, aber ich mag eine Teilansicht für meine BaseRequestData machen von der Art abhängig ist (zum Beispiel AcceleratorRequestData) über den Benutzer aus einem Dropdown-Menü auswählen. Was ich versucht habe verwendet einige jQuery, um einen Controller aufzurufen und eine Teilansicht abhängig von der Dropdown-Liste zu rendern. Hier ist eine meiner Teilansichten, die eine Reihe von Form-Gruppen ist:

@model Synapse.Models.AcceleratorRequestData 

@Html.ValidationSummary(true,"",new {@class = "text-danger"}) 
<div class="form-group"> 
    @Html.LabelFor(m => Model.PutNotional, new {@class = "control-label col-md-2"}) 
    <div class="col-md-10"> 
     @Html.EditorFor(model => model.PutNotional, new {htmlAttributes = new {@class = "form-control"}}) 
     @Html.ValidationMessageFor(model => model.PutNotional, "", new {@class = "text-danger"}) 
    </div> 
</div> 
<div class="form-group"> 
    @Html.LabelFor(m => Model.CallPercentStrike, new { @class = "control-label col-md-2" }) 
    <div class="col-md-10"> 
     @Html.EditorFor(model => model.CallPercentStrike, new { htmlAttributes = new { @class = "form-control" } }) 
     @Html.ValidationMessageFor(model => model.CallPercentStrike, "", new { @class = "text-danger" }) 
    </div> 
</div> 

Welche meinen Platzhalter <div> in meiner Haupt-Ansicht ersetzt:

@using (Html.BeginHorizontalForm()) 
{ 
    @Html.AntiForgeryToken() 

    <hr/> 
    @Html.ValidationSummary(true, "", new {@class = "text-danger"}) 
    <div id="accelRequestPh" style="display: none;"></div> 

    <input type="submit" value="Create" class="btn btn-default" /> 

} 

Aber hier meine Validierung Eigenschaften und Bindungen nicht (natürlich, weil mein BaseRequestData-Objekt nicht an die Instanz meines Request-Objekts gebunden ist). Wie kann ich das machen? Soll ich eine Editorvorlage verwenden? Wenn ich es trotzdem tue, wie wird mein Hauptmodell darüber informiert?

+0

Welchen Zweck hat die Klasse 'Request', die' BaseRequest' als virtuelle Eigenschaft enthält? Ich frage, weil Sie das Request-Objekt nirgendwo verwenden (Sie können nicht validieren, was nicht da ist). –

+0

Ich brauche es für die Navigation. Mein übergeordnetes Objekt ist der Typ Request, den ich gerne erzeuge, und jede Anfrage hat ein BaseRequestData-Objekt, das konkret ist. – coolboyjules

+0

Wäre es besser, eine Schnittstelle für Ihre abstrakte Definition zu verwenden und alles, was 'Request' verwendet, stattdessen die Schnittstelle zu verwenden? Ich frage, weil Sie sagen, Ihre Validierung bricht, weil BaseRequest nicht an Request gebunden ist, aber die Art, wie Sie diesen Code entworfen haben, ist schwer zu sagen, was passiert, ohne die gesamte Quelle zu sehen und wie alles Ihre Abhängigkeitskette verbraucht ich es ist). –

Antwort

0

AcceleratorRequestData auf Ihre Request Klasse hinzufügen:

public class Request 
{ 
    public virtual BaseRequestData RequestData { get; set; } 
    public AcceleratorRequestData acceleratorRequestData { get; set; } 
} 

Dann Modell Ihrer Teilansicht ändern:

@model Synapse.Models.Request.AcceleratorRequestData 
+0

Aber das würde den Zweck meiner abstrakten Klasse besiegen :( – coolboyjules

+0

Warum denkst du "es besiege den Zweck meiner abstrakten Klasse"? Es ist nur eine Klasse als eine Eigenschaft für andere Klasse. Es geht nicht um Ihre Klassenvererbung. – Hadee

+0

Ja, aber der Punkt ist, dass meine RequestData in ihre Kinder morpht, sonst hätte ich einfach die abstrakte Klasse entfernen und alle Kinder manuell hinzufügen können ... – coolboyjules

0

Also gab ich die Drop-down-Rendering verschiedene HTML-Elemente und stattdessen Ich zog die Drop-down die vorherige Seite, so dass sie die konkrete Unterklasse an die Ansicht übergibt. Wie folgt aus:

nennt Meine Dropdown dieser Controller:

/// <summary> 
    /// Get the correct view depending on the dropdown 
    /// </summary> 
    /// <param name="productType"></param> 
    /// <returns></returns> 
    [HttpGet] 
    public ActionResult Create(string productType) 
    { 
     Request request = new Request(); 
     switch (productType) 
     { 
      case "Accelerator": 
       request.RequestData = new AcceleratorRequestData(); 
       request.ColloquialType = ColloquialType.Accelerator; 
       return View(request); 
      case "BarrierAccelerator": 
       request.RequestData = new BarrierAcceleratorRequestData(); 
       request.ColloquialType = ColloquialType.BarrierAccelerator; 
       return View(request); 
      default: 
       return RedirectToAction("Index", "Requests"); 
     } 
    } 

, die eine übergeordnete Ansicht zurück:

@using (Html.BeginHorizontalForm()) 
{ 
    @Html.AntiForgeryToken() 

    <hr/> 
    @Html.ValidationSummary(true, "", new {@class = "text-danger"}) 
    @Html.EditorFor(x => x.RequestData) 

    <input type="submit" value="Create" class="btn btn-default"/> 
} 

verwende ich Editor Vorlagen hier für jedes meiner Kinder BaseRequestData. Hier ist eine:

@model Synapse.Models.AcceleratorRequestData 

@Html.Hidden("ModelType", Model.GetType())   
@Html.ValidationSummary(true,"",new {@class = "text-danger"}) 
<div class="form-group"> 
    @Html.LabelFor(m => Model.PutNotional, new {@class = "control-label col-md-2"}) 
    <div class="col-md-10"> 
     @Html.EditorFor(model => model.PutNotional, new {htmlAttributes = new {@class = "form-control"}}) 
     @Html.ValidationMessageFor(model => model.PutNotional, "", new {@class = "text-danger"}) 
    </div> 
</div> 
<div class="form-group"> 
    @Html.LabelFor(m => Model.CallPercentStrike, new { @class = "control-label col-md-2" }) 
    <div class="col-md-10"> 
     @Html.EditorFor(model => model.CallPercentStrike, new { htmlAttributes = new { @class = "form-control" } }) 
     @Html.ValidationMessageFor(model => model.CallPercentStrike, "", new { @class = "text-danger" }) 
    </div> 
</div> 

Die versteckte HTML-Helfer von diesem Link lautet: ViewModel with List<BaseClass> and editor templates

Und ich hatte auch meine global.cs

public class MvcApplication : HttpApplication 
    { 
     protected void Application_Start() 
     { 
      AreaRegistration.RegisterAllAreas(); 
      FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); 
      RouteConfig.RegisterRoutes(RouteTable.Routes); 
      BundleConfig.RegisterBundles(BundleTable.Bundles); 
      log4net.Config.XmlConfigurator.Configure(new FileInfo(Server.MapPath("~/Web.config"))); 
      ModelBinders.Binders.Add(typeof(BaseRequestData), new BaseRequestDataModelBinder()); 
     } 
    } 

    public class BaseRequestDataModelBinder : DefaultModelBinder 
    { 
     protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType) 
     { 
      ValueProviderResult typeValue = bindingContext.ValueProvider.GetValue(bindingContext.ModelName + ".ModelType"); 
      Type type = Type.GetType(
       (string)typeValue.ConvertTo(typeof(string)), 
       true 
      ); 
      object model = Activator.CreateInstance(type); 
      bindingContext.ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(() => model, type); 
      return model; 
     } 
    } 

Hoffentlich zu bearbeiten, das hilft jemand!

Verwandte Themen