2013-02-26 14 views
12

Jeśli mam widok, który ma model, powiedzmy samochodów ..oddelegowania do innego modelu z formularza w ASP.NET MVC

@model Project.Car 

wewnątrz tego widoku chcę utworzyć formularz, który wysyła dane do nowy model

@using (Html.BeginForm("Add", "Controller")) 
    { 
     @Html.Hidden("ID", "1") 
     @Html.Hidden("UserID", "44") 
     @Html.TextArea("Description") 
    } 

zauważyłem, że jeśli moje działanie jest zdefiniowana z moim ViewModel to nie działa (model jest zawsze null):

[HttpPost] 
    public PartialViewResult Add(ViewModels.NewModel model) 

Jednak, jeśli mogę użyć FormCollection to działa:

[HttpPost] 
    public PartialViewResult Add(FormCollection formCollection) 

Oto ViewModel:

public class NewModel 
{ 
    public int ID { get; set; } 
    public int UserID { get; set; } 
    public string Description { get; set; } 
} 

Moje pytanie brzmi mogę dodawać dane do NewModel od mojej postaci? Widok, w którym się znajduje, jest poprawny, aby być powiązanym z Project.Car. Jest to mały formularz na stronie, który musi opublikować inny zestaw danych, który nie ma nic wspólnego z Project.Car.

+0

Czy można również opublikować ViewModel? – brenton

+0

Pewnie, właśnie go dodałem. – Alex

+0

Ale publikujesz Project.Car. Czy nie? – idipous

Odpowiedz

6

Masz rozbieżność między nazwą swojego modelu i działaniem. W pokazanym przykładzie model nazywa się Add, podczas gdy w swojej akcji używasz ViewModels.NewModel. Co gorsza, twój widok jest mocno wpisany w model o nazwie Car. Niechlujny to wszystko.

więc zacząć od zdefiniowania poprawnego modelu wyświetlania:

public class CarViewModel 
{ 
    public int ID { get; set; } 
    public int UserID { get; set; } 
    public string Description { get; set; } 
} 

a następnie kontroler:

public class CarsController: Controller 
{ 
    public ActionResult Add() 
    { 
     var model = new CarViewModel 
     { 
      // don't ask me, those are the values you hardcoded in your view 
      ID = 1, 
      UserID = 44, 
     }; 
     return View(model); 
    } 

    [HttpPost] 
    public PartialViewResult Add(CarViewModel model) 
    { 
     ... 
    } 
} 

i odpowiedni silnie wpisany widok na modelu Widok:

@model CarViewModel 
@using (Html.BeginForm()) 
{ 
    @Html.HiddenFor(x => x.ID) 
    @Html.HiddenFor(x => x.UserID) 
    @Html.TextAreaFor(x => x.Description) 
    <button type="submit">Add</button> 
} 
+0

Przepraszam, napisałem to podczas pracy nad funkcją szybko i musiałem zmienić nazwy działań i kontrolerów do celów próbnych. Poprawiłem problem. – Alex

1

Twój widok został skonfigurowany do używania modelu typu Project.Carjednak Twoja metoda działania przyjmuje model typu ViewModels.NewModel, , ale także Twoja klasa modelu została opublikowana w typie Add?

je zmienić wszystko, aby dopasować (zakładając Add jest poprawna):

Widok:

@model Add 

Kontroler:

[HttpPost] 
public PartialViewResult Add(Add model) 
4
My question is can I post data to NewModel from my form? 

Krótka odpowiedź brzmi: tak można opublikować Formularz do dowolnego działania kontrolera na dowolnym kontrolerze związanym z dowolnym modelem w aplikacji.

Na przykład, na swoją postać opublikować w „Add” działania na kontrolerze NewModel:

@using (Html.BeginForm("Add", "NewModel")) 
    { 
     @Html.Hidden("ID", "1") 
     @Html.Hidden("UserID", "44") 
     @Html.TextArea("Description") 
    } 

Ponieważ widok jest zdecydowanie wpisane do modelu Car, Można to zmienić i wysłać ViewModel do widoku, którego typ pasuje do Twojego modelu aktualizacji (jak Darin demonstrated), albo trzeba mapować dane post z Car na NewModel w kontrolerze:

na CarController „s Add działanie (Po)

[HttpPost] 
public PartialViewResult Add(Car model) 
{ 
    //now map attribute values from the Car model onto 
    //corresponding attributes of an instance of NewModel 
    NewModel new = new NewModel(); 
    new.ID = model.ID; 
    new.UserID = model.UserID; 
    new.Desc = model.Description; 
    //etc... 

    //update your model/db 
    _db.Add(new); 

    //Redirect however you wish... 
} 

również sprawdzić, jak AutoMapper mapowania obiekt-obiekt, który automatyzuje mapowanie ViewModels na modelach i vice versa.

-3

W tym celu można również utworzyć niestandardowy segregator modelowy.

2

Tak, możesz zdecydowanie wpisać widok do jednego modelu i POST go do innego modelu.

Czyniąc to masz dwie opcje:

  1. ręcznie podaj poprawne nazwy dla każdego pola wejściowego, tak że domyślna spoiwo będzie go zrozumieć i stworzyć model (example).

    Podczas tej czynności oznacza to również, że należy pilnować literówek i nie można uzyskać błędów podczas kompilacji, jeśli błędnie wpisano nazwę właściwości.

  2. Ręcznie utwórz pomocnika HTML w widoku powiązanym z nowym typem modelu. Następnie wygeneruje odpowiedni kod HTML.

    Aby skonstruować pomocnika, potrzebny jest obiekt opakowania, który odsłoniłby instancję modelu w postaci interfejsu IViewDataContainer. Można określić, że opakowanie w dowolnym miejscu, w tym samym modelem:

    public class NewModel 
    { 
        public int ID { get; set; } 
        public int UserID { get; set; } 
        public string Description { get; set; } 
    
        public class WrapperForHtmlHelper : System.Web.Mvc.IViewDataContainer 
        { 
        public System.Web.Mvc.ViewDataDictionary ViewData { get; set; } 
    
        public WrapperForHtmlHelper(NewModel value) 
        { 
         this.ViewData = new System.Web.Mvc.ViewDataDictionary<NewModel>(value); 
        } 
        } 
    } 
    

    Następnie w widoku tworzonej pomocnika związany z wystąpieniem NewModel:

    var ModelToPost = new YourApp.Models.NewModel() { ID = 1, UserID = 43, Description = "" } 
    
    var hlp = new HtmlHelper<YourApp.Models.NewModel> 
         (this.ViewContext, 
          new YourApp.Models.NewModel.WrapperForHtmlHelper(ModelToPost) 
         ); 
    

    A potem wykorzystać pomocnika jak zwykle:

    @hlp.HiddenFor(m => m.ID) 
    @hlp.HiddenFor(m => m.UserID) 
    @hlp.TextAreaFor(m => m.Description) 
    

    Wtedy twój PartialViewResult Add(ViewModels.NewModel model) będzie poprawnie odbierać dane.

Powiązane problemy