سؤال

The default MVC template uses "@DateTime.Now.Year" to display the copyright year, but I'd much rather use NodaTime everywhere.

I'm currently using Ninject to inject an instance of IClock into Controllers that do time or date specific stuff. Is there a recommended way to access a "global IClock" in MVC similar to the "DateTime.Now"? I suppose I could inject the IClock into every Controller then pass it into every view, but it would be nice to have access to something global sometimes.

I know I could use SystemClock.Instance in the Layout template... it would be much nicer to reference a global, testable IClock instead.

هل كانت مفيدة؟

المحلول

You could use a child action.

Start by writing a controller in which you could use dependency injection as usual and which will contain a child action:

public class CopyrightController: Controller
{
    private readonly IClock clock;
    public CopyrightController(IClock clock)
    {
        this.clock = clock;
    }

    [ChildActionOnly]
    public ActionResult Index()
    {
        // In this example I am directly passing the IClock instance
        // to the partial view as model but in a real application
        // you might want to use a view model here
        return PartialView(this.clock);
    }
}

and then you could have a corresponding partial view (~/Views/Copyright/Index.cshtml):

@model IClock
<div>Copyright ...</div>

and finally in your _Layout call this child action:

<footer>
    @Html.Action("Copyright", "Index")
</footer>

نصائح أخرى

If you're looking for a testable DateTime.Now, you could use SystemTime.Now(), as detailed in this post by Ayende Rahien. You can create a Func<DateTime> that defaults to DateTime.Now but that you can set to a specific date in your tests. It saves you introducing another dependency. Here's the func:

public static class SystemTime
{
public static Func<DateTime> Now = () => DateTime.Now;
}

Wherever you would use DateTime.Now you should use SystemTime.Now instead. You can set it in your tests like this:

SystemTime.Now = () => new DateTime(2012, 7, 1).Date;

Provided you have adequate test coverage of your usage of dates, you should catch any instances in which you are using DateTime.Now instead of SystemTime.Now

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top