tag:blogger.com,1999:blog-11712659994806819802024-03-08T00:25:40.741-08:00Treats for your Silicone PetMirko Geffkenhttp://www.blogger.com/profile/08748094891809938994noreply@blogger.comBlogger2125tag:blogger.com,1999:blog-1171265999480681980.post-26155800935848703682009-06-15T06:51:00.000-07:002011-04-01T09:04:33.020-07:00ASP.NET MVC Strongly-Typed ActionLink with Images<p>Today I had the desire to change some of the ActionLinks we have been using from boring text to exciting images (which meant using my image collection as I have no talent whatsoever in drawing anything). Unfortunately I was unable to locate a respective method on the existing HtmlHelper. </p> <p>I am a big fan of the strongly-typed variety of these methods, which are, as of today, only available in the MVC Futures (available at <a href="http://aspnet.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=24471" target="_blank">CodePlex</a>).</p> <p>In my hunt for an efficient (lazy) copy-and-paste solution I came across a thread on Stack Overflow with a comment by <a href="http://stackoverflow.com/questions/989005/make-an-html-actionlink-around-an-image-in-asp-net-mvc" target="_blank">eu-ge-ne</a>. His code does a nice job of getting an image produced, but did not get me the desired strongly-typed implementation I was seeking.</p> <p>His version was this (with a minor fix and my personal dislike of var replaced):<br></p><pre class="code"><span style="color: blue">public static string </span>ActionLinkWithImage(<span style="color: blue">this </span>HtmlHelper html, <span style="color: blue">string </span>imgSrc, <span style="color: blue">string </span>actionName)<br />{<br /> UrlHelper urlHelper = <span style="color: blue">new </span>UrlHelper(html.ViewContext.RequestContext); <br /> <span style="color: blue">string </span>imgUrl = urlHelper.Content(imgSrc); <br /> TagBuilder imgTagBuilder = <span style="color: blue">new </span>TagBuilder(<span style="color: #a31515">"img"</span>); <br /> imgTagBuilder.MergeAttribute(<span style="color: #a31515">"src"</span>, imgUrl); <br /> <span style="color: blue">string </span>img = imgTagBuilder.ToString(TagRenderMode.Normal); <br /> <span style="color: blue">string </span>url = urlHelper.Action(actionName); <br /><br /> TagBuilder tagBuilder = <span style="color: blue">new </span>TagBuilder(<span style="color: #a31515">"a"</span>)<br /> {<br /> InnerHtml = img<br /> }; <br /><br /> tagBuilder.MergeAttribute(<span style="color: #a31515">"href"</span>, url); <br /> <span style="color: blue">return </span>tagBuilder.ToString(TagRenderMode.Normal);<br />}<br /></pre><br /><br />The following does almost the same, but strongly-typed.<br /><pre class="code"><span style="color: blue">public static class </span>HtmlHelperExtensions<br />{<br /> <span style="color: blue">public static string </span>ActionLinkWithImage<TController>(<span style="color: blue">this </span>HtmlHelper html, Expression<Action<TController>> action, <span style="color: blue">string </span>imgSrc) where TController : Controller<br /> {<br /> UrlHelper urlHelper = <span style="color: blue">new </span>UrlHelper(html.ViewContext.RequestContext);<br /> <span style="color: blue">string </span>imgUrl = urlHelper.Content(imgSrc);<br /> TagBuilder imgTagBuilder = <span style="color: blue">new </span>TagBuilder(<span style="color: #a31515">"img"</span>);<br /> imgTagBuilder.MergeAttribute(<span style="color: #a31515">"src"</span>, imgUrl);<br /> <span style="color: blue">string </span>img = imgTagBuilder.ToString(TagRenderMode.Normal);<br /> TagBuilder tagBuilder = <span style="color: blue">new </span>TagBuilder(<span style="color: #a31515">"a"</span>)<br /> {<br /> InnerHtml = img<br /> };<br /> tagBuilder.MergeAttribute(<span style="color: #a31515">"href"</span>, LinkBuilder.BuildUrlFromExpression(html.ViewContext.RequestContext, html.RouteCollection, action));<br /> <span style="color: blue">return </span>tagBuilder.ToString(TagRenderMode.Normal);<br /> }<br /><br /> <span style="color: blue">public static string </span>ActionLinkWithImage<TController>(<span style="color: blue">this </span>HtmlHelper html, Expression<Action<TController>> action, <span style="color: blue">string </span>imgSrc, <span style="color: blue">object </span>imageAttributes, <span style="color: blue">object </span>linkAttributes) where TController : Controller<br /> {<br /> UrlHelper urlHelper = <span style="color: blue">new </span>UrlHelper(html.ViewContext.RequestContext);<br /> <span style="color: blue">string </span>imgUrl = urlHelper.Content(imgSrc);<br /> TagBuilder imgTagBuilder = <span style="color: blue">new </span>TagBuilder(<span style="color: #a31515">"img"</span>);<br /> imgTagBuilder.MergeAttribute(<span style="color: #a31515">"src"</span>, imgUrl);<br /><br /> imgTagBuilder.MergeAttributes(<span style="color: blue">new </span>RouteValueDictionary(imageAttributes));<br /><br /> <span style="color: blue">string </span>img = imgTagBuilder.ToString(TagRenderMode.Normal);<br /><br /> TagBuilder tagBuilder = <span style="color: blue">new </span>TagBuilder(<span style="color: #a31515">"a"</span>)<br /> {<br /> InnerHtml = img<br /> };<br /><br /> tagBuilder.MergeAttributes(<span style="color: blue">new </span>RouteValueDictionary(linkAttributes));<br /> tagBuilder.MergeAttribute(<span style="color: #a31515">"href"</span>, LinkBuilder.BuildUrlFromExpression(html.ViewContext.RequestContext, html.RouteCollection, action));<br /> <span style="color: blue">return </span>tagBuilder.ToString(TagRenderMode.Normal);<br /> }<br />}<br /></pre><br /><br />An example of consumption on your page would then be:<br /><pre class="code"><span style="background: yellow"><%</span><span style="color: blue">= </span>Html.ActionLinkWithImage<FooController>(fc => fc.Edit(deal.ID), "~/Content/Images/edit_16.png", new { style = "border-style: none;", alt = "Edit Foo", title = "Edit Deal" }, null) <span style="background: yellow">%><br /></span></pre><br /><br /><p>Hope this helps someone with the same predicament (Someone feel free to incorporate into the Futures assembly :))</p> Mirko Geffkenhttp://www.blogger.com/profile/08748094891809938994noreply@blogger.com3tag:blogger.com,1999:blog-1171265999480681980.post-11382758703723268512009-06-13T08:58:00.000-07:002011-04-01T09:01:05.462-07:00ASP.NET MVC Form Validation Error with Decimal Parsing<p>Today I tried to put a relatively simple form together and was hoping to be done in a few minutes. Included on the form is an optional field asking for a monetary value. The type in the database is money and using LINQ-to-SQL the type is represented as a decimal. <p>All was well until the user entered a value that decimals generally don’t like to be converted into. Let’s assume ‘aaa’ for the time being. The result I was greeted with was this: <p><pre class="code">The model of type 'Foo' was not successfully updated.</pre></p><p>My desire for ASP.NET MVC to handle this for me and put a nice validation message into the ModelState was just not happening. <br><br>My original code did this: </p><pre class="code">Foo foo = _modelRepository.FindFoo(id);<br />UpdateModel(foo);<br /></pre>The relatively simple fix is:<pre class="code">Foo foo = _modelRepository.FindFoo(id);<br />UpdateModel(foo, <span style="color: #a31515">"SomeStringField"</span>, <span style="color: #a31515">"SomeOtherStringField"</span>);<br /><br /><span style="color: blue">if </span>(!TryUpdateModel(foo, <span style="color: #a31515">"TheDecimalField"</span>))<br />{<br /> ModelState.AddModelError(<span style="color: #a31515">"TheDecimalField"</span>, <span style="color: #a31515">"Does that look like a number to you?"</span>);<br />}<br /><br /></pre> Mirko Geffkenhttp://www.blogger.com/profile/08748094891809938994noreply@blogger.com5