2012-02-23 13 views
8

Ho il seguente codice:dati di Scrittura quando la mia vista del modello ha un costruttore non funziona

[HttpGet] 
public ActionResult Edit(int req) 
{ 
    var viewModel = new EditViewModel(); 
    viewModel.RequestId = int; 
    return View(viewModel); 
} 

[HttpPost] 
Public ActionResult Edit(EditViewModel viewModel) 
{ 
// some code here... 
} 

Funziona benissimo: quando il modulo di modifica viene inviato, ho il regolatore di azione che è chiamato.

Ora mi modificare alcuni po 'il mio codice come questo:

[HttpGet] 
public ActionResult Edit(int req) 
{ 
    var viewModel = new EditViewModel(req); 
    return View(viewModel); 
} 

[HttpPost] 
Public ActionResult Edit(EditViewModel viewModel) 
{ 
// some code here... 
} 

public class EditViewModel() 
{ 
    public EditViewModel(int req) 
    { 
     requestId = req; 
    } 
    ... 
} 

In questa nuova versione, ho un modello di vista con un contructor.

Questa volta, quando il modulo viene postposto, il controller azione non viene mai attivato.

Qualche idea?

Grazie.

risposta

12

Questo è normale. Il modello predefinito di binder non può più istanziare il tuo modello di vista in quanto non ha un costruttore senza parametri. Dovrai scrivere un raccoglitore modello personalizzato se vuoi usare i modelli di vista che non hanno un costruttore predefinito.

Normalmente non è necessario un costruttore personalizzato. Si potrebbe semplicemente avere il vostro vista del modello del genere:

public class EditViewModel() 
{ 
    public int RequestId { get; set; } 
} 

e l'azione POST così:

[HttpPost] 
public ActionResult Edit(EditViewModel viewModel) 
{ 
    // some code here... 
} 

e ora tutto quello che dovete fare è post parametro requestId anziché req e il modello predefinito legatore farà il lavoro.

E se per qualche motivo si voleva utilizzare un modello di vista con costruttore personalizzato, ecco un esempio di come il modello personalizzato legante potrebbe essere simile:

public class EditViewModelBinder : DefaultModelBinder 
{ 
    protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType) 
    { 
     var req = bindingContext.ValueProvider.GetValue("req"); 
     if (req == null) 
     { 
      throw new Exception("missing req parameter"); 
     } 
     int reqValue; 
     if (!int.TryParse(req.AttemptedValue, out reqValue)) 
     { 
      throw new Exception(string.Format("The req parameter contains an invalid value: {0}", req.AttemptedValue)); 
     } 

     return new EditViewModel(reqValue); 
    } 
} 

che sarà registrato nella vostra Application_Start:

ModelBinders.Binders.Add(typeof(EditViewModel), new EditViewModelBinder()); 
+0

Grazie mille per questa risposta precisa. Il motivo per cui mi piacerebbe spostare del codice nel costruttore del mio modello di visualizzazione è di mantenere il mio controller il più leggero possibile. Ho un sacco di codice per "preparare" il mio modello di visualizzazione e "inquina" il mio controller ... La mia prima idea era quella di spostarlo nel costruttore del mio modello di visualizzazione. Forse questa non è una buona idea ... Cosa ne pensi? Grazie comunque. – Bronzato

+0

@Bronzato Ho gli stessi requisiti come voi per passare qualche oggetto nel costruttore di vm e dovrebbe incapsulare come elaborarlo e impostare le sue proprietà. Stai usando la soluzione di cui sopra o ti appoggi qualsiasi altra soluzione per risolvere questo? –

+0

Ho usato la soluzione suggerita sopra. – Bronzato

Problemi correlati