Skip to content

Instantly share code, notes, and snippets.

@mattanja
Last active December 12, 2015 04:39
Show Gist options
  • Save mattanja/4716145 to your computer and use it in GitHub Desktop.
Save mattanja/4716145 to your computer and use it in GitHub Desktop.
Typesafe viewmodel for MVC frameworks
@* For NancyFx - using ViewBase without generic parameter for basic view-model *@
@inherits Nancy.ViewEngines.Razor.NancyRazorViewBase<ViewModel.ViewBase>
@* For ASP.NET MVC - using ViewBase without generic parameter for basic view-model *@
@model ViewModel.ViewBase
@{
// [...]
}
<!DOCTYPE html>
<head>
@* Full IntelliSense support and type-safety without dynamic types *@
<title>@Model.Page.PreFixTitle @Model.Page.Title</title>
</head>
etc...
public abstract class BaseController : Controller {
/// <summary>
/// Setup default page model properties.
/// </summary>
protected ViewBase<TContent> GetDefaultModel<TContent>(ViewBase<TContent> model = null) where TContent : ContentBase
{
if (model == null)
{
model = new ViewBase<TContent>();
}
var page = new PageBase()
{
IsAuthenticated = this.Context.CurrentUser != null,
PreFixTitle = "prefix -",
CurrentUserName = this.Context.CurrentUser != null ? this.Context.CurrentUser.UserName : "",
Errors = new List<ErrorModel>()
};
model.Page = page;
return model;
}
}
public class HomeController : BaseController {
public ActionResult Start() {
var model = this.GetDefaultModel<StartContent>();
model.Page.Title = "Start";
model.Content.Members = dbService.GetMembers(); // This is not using some dynamic but the generic content class.
return View(model);
}
}
@* For NancyFx *@
@inherits Nancy.ViewEngines.Razor.NancyRazorViewBase<ViewModel.ViewBase<ViewModel.StartContent>>
@* For ASP.NET MVC *@
@model ViewModel.ViewBase<ViewModel.StartContent>
@{
Layout = "_Layout.cshtml";
}
<h2>Home</h2>
<div>Start</div>
<ul>
@* Full IntelliSense support and type-safety without dynamic types *@
@foreach (var member in Model.Content.Members) {
<li>@member.Email</li>
}
</ul>
/// <summary>
/// Base view model for the layout.
/// </summary>
public class ViewBase {
public PageBase Page { get; set; }
}
/// <summary>
/// Generic view model to include the view model for the view.
/// </summary>
/// <typeparam name="TContent"></typeparam>
public class ViewBase<TContent> : ViewBase where TContent : ContentBase
{
public TContent Content { get; set; }
}
/// <summary>
/// Base view model for settings of the page and layout.
/// </summary>
public class PageBase
{
public String Title { get; set; }
public String PreFixTitle { get; set; }
public bool IsAuthenticated { get; set; }
public List<ErrorModel> Errors { get; set; }
public string CurrentUserName { get; set; }
}
/// <summary>
/// Base class for the content of a view (generic parameter of ViewBase).
/// </summary>
public abstract class ContentBase
{
}
/// <summary>
/// Sample content view model.
/// </summary>
public class StartContent : ContentBase
{
public List<Mail.Member> Members { get; set; }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment