Thursday, December 3, 2015

Passing additional view data to a Edit to make sharing a EditorTemplate on an Edit and Create view.


Imagine you have a Editor in Shared\EditorTemplates\Person.cs for an object (Person in this example) and two views for an Order entity that is showing edit fields for Order obeject and the Person object. The two EditorTemplates are Person\Edit.cshtml and Person\Create.cshtml. To use the Person EditorTemplate in the Order Edit AND Create view we need to make sure we always pass a value for the Person.OrderID. If we don't do this, the problem is that when we use the editor in the context of the Order\Create.cshtml View the Model is null and validation for the hidden field will have a value of null. When it is on Order\Edit.cshtml the model will not be null and we will have a value for model (a Person object) and thus have the value Model.OrderID. It is really the Create that requires this work around, but we want to be able to use the EditorTemplate even when it is on a Create view. Below is the code needed

Code located in the Order\Edit.cshtml View
model in this context is the Order object
NOTE: We ARE passing MyOrderID value here since we do need the editor to know and keep the value.

@Html.EditorFor(model => model.Person, new { MyOrderID = Model.OrderID })

NOTE: When we set MyOrderID, it is scoped to the EditorTemplate that we are passing the value to. However, if we put the value in the ViewBag or ViewData directly (at the top or Order\Edit.cshtml for example) then it is available to all Views and EditorTemplates in this context.

Code located in the Order\Create.cshtml View
model in this context is the Order object
NOTE: we are not passing the MyOrderID value here since we just need any value (-1 was arbitrarily chosen to be safe) and will be assigned by the Entity Framework when it is saved to the database. Most importantly it will pass the validation and the model will be valid until then.

@Html.EditorFor(model => model.Person)
Code in the partial view ( in EditorTemplates folder makes it a template) for the Person object.
model in this context is the Person object
NOTE: If no value is passed using ViewBag.MyOrderID then we use -1, otherwise we use the passed value (usually from the Order\Edit.cshtml View)

@Html.HiddenFor(model => model.OrderID, new { Value = ViewBag.MyOrderID ?? -1 })


You can also use a strongly-typed ViewModel and pass all data to it instead of using the ViewBag.

No comments: