0
votes

Suppose I have a Vehicle class and two child classes like so:

public class Vehicle
{
    public string Model { get; set; }
    public string Color { get; set; }
}

public class Car : Vehicle
{
    public string Seats { get; set; }
}

public class Truck : Vehicle
{
    public string MaxLoad { get; set; }
}

My view to create a car or a truck contains a drop down list where you choose car or truck and depending on what you choose the correct form loads into the div with query.

Here is how I implemented this:

  • I created a partial view containing a form to create a car with Model, Color and Seats inputs.
  • Another partial view with a form to create a Truck with Model, Color and MaxLoad inputs.
  • Each form submits to its own controller method i.e:

    [HttpPost] public ActionResult CreateCar(Car newCar) { .... }

and same for CreateTruck.

  • I have a createVehicle view that contains the drop down list, an empty div with an id and some jquery code that loads one of the car or truck partial views into the div.

Now everything works but if i need to change something in my vehicle model, i would then have to change each partial view and each controller method.

So what i'm asking is how do I go about to implement the most optimal way to submit the models in this case?

Optimally I would have:

  • One controller method onto which I post the models
  • The createVehicle view containing the Vehicle properties and each partial view only containing its own additional properties.
1
are these ViewModels or domain models?T McKeown
FWIW, it's generally a good idea to suffix view models with ViewModel or VM so it's obvious that they aren't entities.Chris Pratt

1 Answers

0
votes

If you have a ViewModel like:

public class VehicleViewModel
{
  public Vehicle Vehicle { get; set; }
  public string Action { get; set; }
}

public class AddTruckModel
{
  public Truck Truck { get; set; }
}

public class AddCarModel
{
  public Car Car { get; set; }
}

In the controller you did (seriously rough example):

public ActionResult(int? vehicleType)
{
  var model = new VehicleViewModel;
  if (!vehicleType.hasValue || vehicleType.Value == 1)
  {
    model.Vehicle = new Car();
    model.Action = "AddCar";
  }
  else
  {
    model.Vehicle = new Truck()
    model.Action = "AddTruck";
  }

  if (Request.IsAjaxRequest())
  { 
    return Partial(model);
  }
  return View(model);
}

public ActionResult AddCar(AddCarModel model)
{
}

public ActionResult AddTruck(AddTruckModel model)
{
}

And you use a view like:

@model VehicleViewModel

@using(html.BeginForm(Model.Action, "Vehicle", new { id="vehicleForm" }))
{
  <div id="vehicle-editor">
  //very hacky, I normally return json with embedded html
  @Html.HiddenFor(m => m.Action)
  @Html.EditorFor(m => m.Vehicle)
  </div>
}

You'll notice that the Editor creates html inputs for Car not just Vehicle. You can use this to your advantage.

I would wrap the EditorFor in a html element (div for example) and when the drop down changes, Ajax a call to pull a partial for another vehicle html fragment (say using jQuery). As for the post back, I would also in the same javascript/jquery event for the drop down, change the action for the form.

Please note this is just a prototype/spike, I would not actually write it like this.