Reputation: 4582
I am creating a partial view to display a record's audit stamps...i.e.
I currently have created a new sub-class in all my viewmodels with .AuditStamps that contains these properties, populate that in my controller and pass it to the partial.
Here is an example of one of my view Models. Note the AudiStamps sub-class
public class ItemViewModel
{
public Item Item { get; set; }
public AuditStampsViewModel AuditStamps { get; set; }
}
Here is my partial, suing this sub-class
@model OTIS.AppServ.Shared.AuditStampsViewModel
<hr />
<div class="twoColumn floatLeft">
<div class="editor-field">
<b>Created By:</b>
@Html.DisplayFor(model => model.CreatedByName) on @Html.DisplayFor(model => model.CreatedOn)
</div>
</div>
<div class="twoColumn floatLeft">
<div class="editor-field" style="text-align:right;">
<b>Modified By:</b>
@Html.DisplayFor(model => model.ModifiedByName) on @Html.DisplayFor(model => model.ModifiedOn)
</div>
</div>
But I was wondering since all my classes will have these common properties, do I really need to go through adding and populating this sub-class. The only reason I am, is because I couldn't figure out how to declare a generic model in the partial...I was hoping the partial would just work if I didn't declare the model, but it doesn't. I get an error:
An expression tree may not contain a dynamic operation
How can I achieve this? Seems like something an Interface would solve just using classes, but not sure if the same concept applies using Partials (i.e. stating a partial implements an IAuditStamps inteface???)
Upvotes: 1
Views: 1733
Reputation: 4582
In the end, I set the model of the partial to be an interface, and then make sure my classes also implemented an interface like so:
Create the IAuditStamps interface
public interface IAuditStamps
{
int CreatedById { get; set; }
string CreatedByName { get; set; }
DateTime CreatedOn { get; set; }
int ModifiedById { get; set; }
string ModifiedByName { get; set; }
DateTime ModifiedOn { get; set; }
}
My Class that implements the interface
public partial class Item : IEntityId, ICompanyId, IAuditStamps
The ItemViewModel (which uses the above class Item)
public class ItemViewModel
{
public Item Item { get; set; }
}
The Partial
@model OTIS.domain.IAuditStamps
<hr />
<div class="twoColumn floatLeft">
<div class="editor-field">
<b>Created By:</b>
@Html.DisplayFor(model => model.CreatedByName) on @Html.DisplayFor(model => model.CreatedOn)
</div>
</div>
<div class="twoColumn floatLeft">
<div class="editor-field" style="text-align:right;">
<b>Modified By:</b>
@Html.DisplayFor(model => model.ModifiedByName) on @Html.DisplayFor(model => model.ModifiedOn)
</div>
</div>
Calling the partial:
@Html.Partial("_AuditStamps", Model.Item)
Upvotes: 2
Reputation: 7705
That's a prime candidate for a ViewModel
base class that all your view models can inherit from:
public abstract class ViewModel
{
public DateTime CreatedOn { get; set; }
public string CreatedBy { get; set; }
public DateTime ModifiedOn { get; set; }
public string ModifiedBy { get; set; }
}
public class ItemViewModel : ViewModel
{
public Item Item { get; set; }
}
Your partial could then have the ViewModel
as its model type to bind to the relevant properties. Any view requiring that partial should have its model inheriting from the base ViewModel, so the properties will all be available for model binding.
Upvotes: 1