dynamic, Why not?
In these days, people begin to expertise some new features in .NET 4.0. And I am same to them as well. One of features I like and write to this post is dynamic keyword. It is not new, at least in PHP, Python, Ruby... But in .NET world, I think it is new and ship to .NET 4.0 as a default. And some of projects are ported to .NET based on DLR as IronPython, IronRuby. We can use dynamic keyword in anywhere in our project. How do you think about it? So dynamite, isn’t it? :D. Some of people are didn’t like it, some else are love it. How about you? With me, I only try to utilize a new feature in .NET 4.0 for make my work is easier.
Today I obstacle issue when I try to implement an
error management in
my application. All things will not be hard to get if I
didn’t separate all base classes to one assembly and try to
reference it from my
ASP.NET MVC solution.
It is meaning all base controller, base view model and some
of helpers, extensions are live in one assembly (called it
was
WebInfrastructure).
And try avoiding
acyclic dependency
between
WebInfrastructure and
Web; certainly we
will only reference
WebInfrastructure from Web and
no reverse
reference direction from
Web in
WebInfrastructure.
And now if we have one class
MySettings in Web and
want to the
WebInfrastructure can
use it. How can we achieve this? This is a place that the
dynamic come to.
In
WebInfrastructure project, I have
+ AuthorizedController
[Authorize]
[HandleError]
public class AuthorizedController : Controller
{
public AuthorizedController(dynamic mySettings)
{
MySettings = mySettings;
}
......, etc
/// <summary>
/// Gets or sets the settings.
/// Its should be dynamic because this class inside the Infrastructure project that not reference to Web project
/// so it cannot get MySetting from this class
/// </summary>
/// <value>The settings.</value>
protected dynamic MySettings { get; set; }
protected override void OnException(ExceptionContext filterContext)
{
if (filterContext == null)
return;
// Get exception from filter context
var ex = filterContext.Exception ?? new Exception("No further information exists.");
filterContext.ExceptionHandled = true;
var data = new ErrorViewModel();
if (MySettings != null)
{
var isShowErrorMessage = MySettings.IsShowErrorMessage;
if (isShowErrorMessage)
{
data.ErrorMessage = HttpUtility.HtmlEncode(ex.Message);
data.TheException = ex;
}
else
{
// TODO: try to use log4net to log error here
// LogException(ex);
}
}
filterContext.Result = View("Error", data);
}
}
+ ErrorViewModel
public class ErrorViewModel
{
public string ErrorMessage { get; set; }
public Exception TheException { get; set; }
}
In
Web
project
+ MySettings, it is simple, and just read the
config from web.config
public class MySettings : ISectionConfiguration
{
public void Add(string sectionName, string sectionValue, List<KeyValuePair<string, string>> valuePairs)
{
//throw new NotImplementedException();
}
public const string SECTION_NAME = "mysettings";
...., etc
public bool IsShowErrorMessage { get; set; }
}
+ Error view
<asp:Content ID="errorTitle" ContentPlaceHolderID="TitleContent" runat="server">
Error
</asp:Content>
<asp:Content ID="errorContent" ContentPlaceHolderID="MainContent" runat="server">
<h2>
Oops: The system got a critical error. Please contact with system administrator
for resolve this error.
</h2>
<% if (!string.IsNullOrEmpty(Model.ErrorMessage))
{%>
<div>
<h3>
Error message:
</h3>
<p>
<%= Model.ErrorMessage%>
</p>
</div>
<%
}%>
<% if (Model.TheException != null)
{%>
<div>
<h3>
Stack trace:
</h3>
<p style="color: #ff0000;">
<%= Model.TheException.StackTrace %>
</p>
</div>
<div>
<h3>
Source of error:
</h3>
<p>
<%= Model.TheException.Source %>
</p>
</div>
<%
}%>
</asp:Content>
+ Controller
public class HomeController : AuthorizedController
{
public HomeController(MySettings mySettings)
: base(mySettings)
{
}
public ActionResult Index()
{
ViewData["Message"] = "Welcome to ASP.NET MVC!";
return View();
}
public ActionResult About()
{
return View();
}
}
Notes: We used Unity for IoC container in this post. so its configuration look like this:
var mySettings = SectionConfiguration.GetInstance<MySettings>(MySettings.SECTION_NAME);
ObjectFactory.RegisterInstance(mySettings);
And in run-time, Unity will inject all dependency
instances into constructors that have most parameters. As
here is
public HomeController(MySettings mySettings)
: base(mySettings)
{
}
Because I need the IsShowMessageError fields in MySettings, but I cannot reference it from WebInfratructure. So I must use the dynamic at this layer for MySetttings, this concrete implementation will be recover when app started (run-time). It’s really cool, isn’t it? But sometimes, I think it is violate the acyclic dependency. I don’t know. So I really love to hear a feedback from you.