2012-02-23 13 views
8

Mam następujący kod:dane umieszczania kiedy mój widok model ma konstruktora nie działa

[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... 
} 

to działa dobrze: gdy formularz edycji jest wysłane, mam kontrolera akcji, która jest tzw.

Teraz zmodyfikować niektóre małe nieco mój kod tak:

[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; 
    } 
    ... 
} 

W tej nowej wersji, mam model widok z contructor.

Tym razem, kiedy mój formularz zostanie wysłany z powrotem, kontroler akcji nigdy nie jest uruchamiany.

Każdy pomysł?

Dzięki.

Odpowiedz

12

To normalne. Domyślny segregator modelu nie może już utworzyć instancji modelu widoku, ponieważ nie ma konstruktora bez parametrów. Będziesz musiał napisać niestandardowy spinacz modelu, jeśli chcesz używać modeli widoku, które nie mają domyślnego konstruktora.

Zwykle nie potrzebujesz takiego niestandardowego konstruktora. może po prostu mieć swój widok modelu tak:

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

i działania POST tak:

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

i teraz wszystko, co musisz zrobić, to POST parametr requestId zamiast req a domyślnym modelem spinacz wykona zadanie.

A jeśli z jakiegoś powodu chciał użyć modelu widok z niestandardowego konstruktora, oto przykład jak spoiwo niestandardowy wzór może wyglądać następująco:

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); 
    } 
} 

który zostanie zarejestrowany w Application_Start:

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

Dziękuję bardzo za tę dokładną odpowiedź. Powodem, dla którego chciałbym przenieść jakiś kod do konstruktora mojego modelu widoku jest utrzymanie mojego kontrolera tak lekkiego, jak to tylko możliwe. Mam dużo kodu, aby "przygotować" mój model widoku i "zanieczyścić" mojego kontrolera ... Moim pierwszym pomysłem było przeniesienie go do konstruktora mojego modelu widoku. Może to nie jest dobry pomysł ... Co myślisz? Dzięki i tak. – Bronzato

+0

@Bronzato Mam takie same wymagania jak ty, aby przekazać jakiś obiekt w konstruktorze vm i powinien on hermetyzować sposób jego przetwarzania i ustawić własne właściwości. Czy korzystasz z powyższego rozwiązania, czy też proponujesz inne rozwiązanie, aby to rozwiązać? –

+0

Użyłem rozwiązania sugerowanego powyżej. – Bronzato

Powiązane problemy