1

This is the closest thing I could find to this specific answer, but doesn't quite answer it for me. How can I create a Html Helper like Html.BeginForm

I have a current html.helper that hides (or shows) content based on the current server time. It's not really a problem, but an improvement I'd love to see here. So the HTML helper works like this:

Html.DurationHtml works like this:

public static IHtmlString DurationHtml(this HtmlHelper html, string StartDateTime, string EndDateTime)
    {
        if (CentralLibrary.WithinDatespan(StartDateTime, EndDateTime))
        {
            var writer = html.ViewContext.Writer;
            return html.Raw(htmlContent);
        }
        else
        {
            return null;
        }
    }

CentralLibrary.WithinDatespan(start,end) is just a method that compares the current time (or a provided simulated time) with the date/times specified and returns true or false.

I implement it like so:

@Html.DurationHtml("<a href=\"link\">Content</a>", "12/12/2015 12:00:01pm","12/12/2017 12:00:01pm") 

This works and does exactly what I want it to do, very well. My hope for an improvement here is to take the content out of the double quotes so that I don't have to escape the double quotes. The caveat here is that I cannot have the content sent to the browser at all. I know I could wrap a container with display set to none, but the content cannot be sent at all as some of the info may not be for public eyes until certain times. Is there a way I can make the html helper work like this and keep the content from being sent to the browser?

@using(Html.DurationHtml("12/12/2015 12:00:01pm","12/12/2017 12:00:01pm")){

     <a href="link">Content</a>

}
Community
  • 1
  • 1
EHaltom
  • 147
  • 10

3 Answers3

0

A Razor @if statement is all you need.

  @if (CentralLibrary.WithinDatespan("12/12/2015 12:00:01pm","12/12/2017 12:00:01pm"))
  {
      <a href="link">Content</a>
  }
  • This is very true and does seem to be exactly what I am trying to accomplish. I guess I got caught up on a statement I heard once. "If you're putting if statements into your views, you might not be doing it right". I will go with this solution, thanks for the help buffjape – EHaltom Nov 23 '15 at 16:21
0

You should be building the markup for your anchor tag from the HTML helper.

public static MvcHtmlString DurationHtml(this HtmlHelper helper, DateTime start, 
                                      DateTime end, string link)
{
    //Replace the below If with your custom condition.
    if (end>start)
    {
        return new MvcHtmlString(string.Format("<a href='{0}'>{1}</a>", link,"Content"));
    }
    return new MvcHtmlString("");    
}

And you call it in your razor view like

 @Html.DurationHtml(Model.StartDate,Model.EndDate,"linkYouWant")
Shyju
  • 214,206
  • 104
  • 411
  • 497
  • Thank you Shyju, but the link was just an example of the content that will be in there. I use the helper to display general html. So sometimes it'll be a link, sometimes a paragraph and sometimes an image with a paragraph. It's not for a specific use, just general HTML. – EHaltom Nov 23 '15 at 16:17
  • @EHaltom You can render any HTML from your helper method – Shyju Nov 23 '15 at 16:18
0

You don't need a helper at all for this. Using quotes, the helper makes for slighly less code, but given how you want it to work, there's virtually no difference between that and just handling it directly in the view. Compare:

@if (DateTime.Now > new DateTime(2015, 12, 12, 12, 0, 1) && DateTime.Now < new DateTime(2017, 12, 12, 12, 0, 1))
{
    <a href="link">Content</a>
}

Versus:

@using (Html.DurationHtml("12/12/2015 12:00:01pm","12/12/2017 12:00:01pm"))
{
    <a href="link">Content</a>
}

The only difference is the conditional looks a little complex, but I'd argue it's actually better that way as the code is self-documenting, whereas someone would have know how to use your helper. Regardless, you could still clean it up a little and still have nearly as succinct code:

@{
    var rangeStart = new DateTime(2015, 12, 12, 12, 0, 1);
    var rangeEnd = new DateTime(2017, 12, 12, 12, 0, 1);
    if (DateTime.Now > rangeStart  && DateTime.Now < rangeEnd)
    {
        <a href="link">Content</a>
    }
}

Even though, that's slightly more code, to my eyes, it's infinitely more clear. Or, given that you're utilizing a utility method in the helper, you could just do the same in your view and actually have less code than you would using the helper:

@if (CentralLibrary.WithinDatespan("12/12/2015 12:00:01pm","12/12/2017 12:00:01pm"))
{
        <a href="link">Content</a>
}

Long and short, if you're going to create a custom helper, it should have real value. Abstraction is a trade-off between reusability and obfuscation of logic. For something this simple, it's better to just have the logic in place, as the reusability is minimal (it's ultimately just a simple conditional).

Chris Pratt
  • 232,153
  • 36
  • 385
  • 444
  • Very helpful Chris, and you're 100% right. I was trying to separate logic from the view as much as possible and lost sight of the simple answer. Thank you. – EHaltom Nov 23 '15 at 16:25