<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Concurrent Development &#187; ASP.NET</title>
	<atom:link href="http://www.concurrentdevelopment.co.uk/blog/index.php/category/aspnet/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.concurrentdevelopment.co.uk/blog</link>
	<description>Musings and tips from the Concurrent Development guys</description>
	<lastBuildDate>Tue, 22 Feb 2011 09:50:45 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1</generator>
		<item>
		<title>ASP.NET MVC LinkButton with HtmlHelper extensions</title>
		<link>http://www.concurrentdevelopment.co.uk/blog/index.php/2011/02/asp-net-mvc-linkbutton-with-htmlhelper-extensions/</link>
		<comments>http://www.concurrentdevelopment.co.uk/blog/index.php/2011/02/asp-net-mvc-linkbutton-with-htmlhelper-extensions/#comments</comments>
		<pubDate>Tue, 22 Feb 2011 09:50:45 +0000</pubDate>
		<dc:creator>peter</dc:creator>
				<category><![CDATA[ASP.NET]]></category>
		<category><![CDATA[MVC]]></category>

		<guid isPermaLink="false">http://www.concurrentdevelopment.co.uk/blog/?p=75</guid>
		<description><![CDATA[Download code We&#8217;re really loving using ASP.NET MVC3 for so many reasons, not least the way in which Microsoft seem to have embraced externally developed tools such as jQuery. In Visual Studio the whole experience feels really cohesive and extending it is a breeze as this post will show. Something we have found missing that [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://bit.ly/hYY82n">Download code</a></p>
<p>We&#8217;re really loving using ASP.NET MVC3 for so many reasons, not least the way in which Microsoft seem to have embraced externally developed tools such as <a href="http://jquery.com">jQuery</a>.  In Visual Studio the whole experience feels really cohesive and extending it is a breeze as this post will show.</p>
<p>Something we have found missing that seems an unusual oversight is an HtmlHelper extension method for submit buttons.  Now I know it&#8217;s not much to write:</p>
<pre class="prettyprint"><code>&lt;input type="submit" value="sign in" /&gt;</code></pre>
<p>but it would seem much neater to do this:</p>
<pre class="prettyprint"><code>@Html.Submit("sign in")</code></pre>
<p>(btw we&#8217;re using the <a href="http://weblogs.asp.net/scottgu/archive/2010/07/02/introducing-razor.aspx">razor view engine</a>).</p>
<p><strong>Html.Submit</strong></p>
<p>It&#8217;s easy enough to write your own HtmlHelper extension methods for the submit button:</p>
<pre class="prettyprint"><code>        /// &lt;summary&gt;
        /// Returns an HTML submit button
        /// &lt;/summary&gt;
        /// &lt;param name="htmlHelper"&gt;&lt;/param&gt;
        /// &lt;returns&gt;&lt;/returns&gt;
        public static MvcHtmlString Submit(this HtmlHelper htmlHelper)
        {
            return htmlHelper.Submit("submit", null);
        }

        /// &lt;summary&gt;
        /// Returns an HTML submit button
        /// &lt;/summary&gt;
        /// &lt;param name="htmlHelper"&gt;&lt;/param&gt;
        /// &lt;param name="value"&gt;The text for the button&lt;/param&gt;
        /// &lt;returns&gt;&lt;/returns&gt;
        public static MvcHtmlString Submit(this HtmlHelper htmlHelper, string value)
        {
            return htmlHelper.Submit(value, null);
        }

        /// &lt;summary&gt;
        /// Returns an HTML submit button
        /// &lt;/summary&gt;
        /// &lt;param name="htmlHelper"&gt;&lt;/param&gt;
        /// &lt;param name="value"&gt;The text for the button&lt;/param&gt;
        /// &lt;param name="htmlAttributes"&gt;The html attributes to apply to the button&lt;/param&gt;
        /// &lt;returns&gt;&lt;/returns&gt;
        public static MvcHtmlString Submit(this HtmlHelper htmlHelper, string value, object htmlAttributes)
        {
            // init a tag builder
            TagBuilder tb = new TagBuilder("input");

            // get the attributes
            var attributes = HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes) as IDictionary&lt;string, object&gt;;

            // set the attributes
            tb.MergeAttributes&lt;string, object&gt;(attributes);

            // set the type
            tb.MergeAttribute("type", "submit", true);

            // set the value
            tb.MergeAttribute("value", value);

            // return self closing
            return new MvcHtmlString(tb.ToString(TagRenderMode.SelfClosing));
        }
</code></pre>
<p><strong>Html.SubmitImage</strong></p>
<p>What about an input button (aka the old web forms ImageButton control), well that&#8217;s pretty straightforward too:</p>
<pre class="prettyprint"><code>        /// &lt;summary&gt;
        /// Returns an input type=image
        /// &lt;/summary&gt;
        /// &lt;param name="htmlHelper"&gt;&lt;/param&gt;
        /// &lt;param name="imageUrl"&gt;The url of the image&lt;/param&gt;
        /// &lt;returns&gt;&lt;/returns&gt;
        public static MvcHtmlString SubmitImage(this HtmlHelper htmlHelper, string imageUrl)
        {
            return htmlHelper.SubmitImage(imageUrl, null);
        }

        /// &lt;summary&gt;
        /// Returns an input type=image
        /// &lt;/summary&gt;
        /// &lt;param name="htmlHelper"&gt;&lt;/param&gt;
        /// &lt;param name="imageUrl"&gt;The url of the image&lt;/param&gt;
        /// &lt;param name="htmlAttributes"&gt;The html attributes to apply to the button&lt;/param&gt;
        /// &lt;returns&gt;&lt;/returns&gt;
        public static MvcHtmlString SubmitImage(this HtmlHelper htmlHelper, string imageUrl, object htmlAttributes)
        {
            // init a tag builder
            TagBuilder tb = new TagBuilder("input");

            // get the attributes
            var attributes = HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes) as IDictionary&lt;string, object&gt;;

            // set the attributes
            tb.MergeAttributes&lt;string, object&gt;(attributes);

            // set the type
            tb.MergeAttribute("type", "image", true);

            // set the image url
            tb.MergeAttribute("src", imageUrl);

            // set the alt attribute
            tb.MergeAttribute("alt", "submit");

            // return self closing
            return new MvcHtmlString(tb.ToString(TagRenderMode.SelfClosing));
        }
</code></pre>
<p>And you can now use this like so:</p>
<pre class="prettyprint"><code>@Html.SubmitImage(Url.Content("~/url/to/image.png"))</code></pre>
<p><strong>Html.SubmitLink</strong></p>
<p>Ok, so far so good, what about the good old LinkButton?  I&#8217;ve seen several posts around the internet that we should be using ActionLink, but that doesn&#8217;t submit the form.  So, using the principles of unobtrusive javascript we create the following extension:</p>
<pre class="prettyprint"><code>        /// &lt;summary&gt;
        /// Returns an A tag with a nested SPAN used to submit a form, requires jquery.link-button.js
        /// &lt;/summary&gt;
        /// &lt;param name="htmlHelper"&gt;&lt;/param&gt;
        /// &lt;returns&gt;&lt;/returns&gt;
        public static MvcHtmlString SubmitLink(this HtmlHelper htmlHelper)
        {
            return htmlHelper.SubmitLink("submit");
        }

        /// &lt;summary&gt;
        /// Returns an A tag with a nested SPAN used to submit a form, requires jquery.link-button.js
        /// &lt;/summary&gt;
        /// &lt;param name="htmlHelper"&gt;&lt;/param&gt;
        /// &lt;param name="linkText"&gt;The text for the link button&lt;/param&gt;
        /// &lt;returns&gt;&lt;/returns&gt;
        public static MvcHtmlString SubmitLink(this HtmlHelper htmlHelper, string linkText)
        {
            return htmlHelper.SubmitLink(linkText, null);
        }

        /// &lt;summary&gt;
        /// Returns an A tag with a nested SPAN used to submit a form, requires jquery.link-button.js
        /// &lt;/summary&gt;
        /// &lt;param name="htmlHelper"&gt;&lt;/param&gt;
        /// &lt;param name="linkText"&gt;The text for the link button&lt;/param&gt;
        /// &lt;param name="htmlAttributes"&gt;The html attributes to apply to the button&lt;/param&gt;
        /// &lt;returns&gt;&lt;/returns&gt;
        public static MvcHtmlString SubmitLink(this HtmlHelper htmlHelper, string linkText, object htmlAttributes)
        {
            // init a tag builder
            TagBuilder tb = new TagBuilder("a");

            // get the attributes
            var attributes = HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes) as IDictionary&lt;string, object&gt;;

            // set the attributes
            tb.MergeAttributes&lt;string, object&gt;(attributes);

            // add the data attribute
            tb.MergeAttribute("data-link-button", "true");

            // add a nothing href
            tb.MergeAttribute("href", "#");

            // set the inner html
            tb.InnerHtml = String.Format("&lt;span&gt;{0}&lt;/span&gt;", linkText);

            // return self closing
            return new MvcHtmlString(tb.ToString());
        }
</code></pre>
<p>You will notice that the markup rendered by this contains a span nested within the a tag.  We implemented the extension method like this to make it easy for us to do style the buttons nicely using the <a href="http://www.oscaralexander.com/tutorials/how-to-make-sexy-buttons-with-css.html">sliding doors technique</a>.</p>
<p>Now, this won&#8217;t work without the associated javascript file (jquery.link-button.js):</p>
<pre class="prettyprint"><code>/// &lt;reference path="jquery-1.5.js" /&gt;
(function ($) {
    $("a[data-link-button=true]").live("click", function (e) {
        e.preventDefault();
        var form = $(this).parents('form').first().submit();
        return false;
    });
})(jQuery);
</code></pre>
<p>As you can see this relies on jQuery so you&#8217;ll need a reference to that too. </p>
<p><a href="http://bit.ly/hYY82n">Download code</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.concurrentdevelopment.co.uk/blog/index.php/2011/02/asp-net-mvc-linkbutton-with-htmlhelper-extensions/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Custom ValidationAttribute for comparing properties.</title>
		<link>http://www.concurrentdevelopment.co.uk/blog/index.php/2011/01/custom-validationattribute-for-comparing-properties/</link>
		<comments>http://www.concurrentdevelopment.co.uk/blog/index.php/2011/01/custom-validationattribute-for-comparing-properties/#comments</comments>
		<pubDate>Fri, 14 Jan 2011 11:30:04 +0000</pubDate>
		<dc:creator>peter</dc:creator>
				<category><![CDATA[ASP.NET]]></category>

		<guid isPermaLink="false">http://www.concurrentdevelopment.co.uk/blog/?p=60</guid>
		<description><![CDATA[We&#8217;re using ASP.NET MVC3 on our latest project and have been really impressed so far.  One of the coolest things I have come across is using DataAnnotations to decorate the model classes and having the framework wire up all the validation and error messages.  It is truly great &#8211; you can find out more at [...]]]></description>
			<content:encoded><![CDATA[<p>We&#8217;re using ASP.NET MVC3 on our latest project and have been really impressed so far.  One of the coolest things I have come across is using DataAnnotations to decorate the model classes and<em> </em>having the framework wire up all the validation and error messages.  It is truly great &#8211; you can find out more at Scott Guthrie&#8217;s <a title="ASP.NET MVC 2: Model Validation" href="http://weblogs.asp.net/scottgu/archive/2010/01/15/asp-net-mvc-2-model-validation.aspx">blog post on the subject</a> (for MVC2 but the principles are the same).</p>
<p>There&#8217;s no built in support for comparing two properties though this has been addressed to a certain extent by the CompareAttribute in the System.Web.Mvc namespace in MVC3, David Hayden has <a title="CompareAttribute in ASP.NET MVC 3 - Compare Properties During Validation" href="http://davidhayden.com/blog/dave/archive/2011/01/01/CompareAttributeASPNETMVC3.aspx">blogged about it here</a>.  This attribute allows you to specify that the value of two properties should be equal, but doesn&#8217;t help with greater than or less than operations.  This kind of thing would be really useful to specify that the StartDate of an Appointment should be before the EndDate.</p>
<p>So I have written my own custom comparison validation attribute for use with asp.net mvc in the style of the built in data annotations.</p>
<pre class="prettyprint"><code>    /// &lt;summary&gt;
    /// Specifies that the field must compare favourably with the named field, if objects to check are not of the same type
    /// false will be return
    /// &lt;/summary&gt;
    [AttributeUsageAttribute(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = false)]
    public class CompareValuesAttribute : ValidationAttribute
    {
        /// &lt;summary&gt;
        /// The other property to compare to
        /// &lt;/summary&gt;
        public string OtherProperty { get; set; }

        public CompareValues Criteria { get; set; }

        /// &lt;summary&gt;
        /// Creates the attribute
        /// &lt;/summary&gt;
        /// &lt;param name="otherProperty"&gt;The other property to compare to&lt;/param&gt;
        public CompareValuesAttribute(string otherProperty, CompareValues criteria)
        {
            if (otherProperty == null)
                throw new ArgumentNullException("otherProperty");

            OtherProperty = otherProperty;
            Criteria = criteria;
        }

        /// &lt;summary&gt;
        /// Determines whether the specified value of the object is valid.  For this to be the case, the objects must be of the same type
        /// and satisfy the comparison criteria. Null values will return false in all cases except when both
        /// objects are null.  The objects will need to implement IComparable for the GreaterThan,LessThan,GreatThanOrEqualTo and LessThanOrEqualTo instances
        /// &lt;/summary&gt;
        /// &lt;param name="value"&gt;The value of the object to validate&lt;/param&gt;
        /// &lt;param name="validationContext"&gt;The validation context&lt;/param&gt;
        /// &lt;returns&gt;A validation result if the object is invalid, null if the object is valid&lt;/returns&gt;
        protected override ValidationResult IsValid(object value, ValidationContext validationContext)
        {
            // the the other property
            var property = validationContext.ObjectType.GetProperty(OtherProperty);

            // check it is not null
            if (property == null)
                return new ValidationResult(String.Format("Unknown property: {0}.", OtherProperty));

            // check types
            if (validationContext.ObjectType.GetProperty(validationContext.MemberName).PropertyType != property.PropertyType)
                return new ValidationResult(String.Format("The types of {0} and {1} must be the same.", validationContext.DisplayName, OtherProperty));

            // get the other value
            var other = property.GetValue(validationContext.ObjectInstance, null);

            // equals to comparison,
            if (Criteria == CompareValues.EqualTo)
            {
                if (Object.Equals(value, other))
                    return null;
            }
            else if (Criteria == CompareValues.NotEqualTo)
            {
                if (!Object.Equals(value, other))
                    return null;
            }
            else
            {
                // check that both objects are IComparables
                if (!(value is IComparable) || !(other is IComparable))
                    return new ValidationResult(String.Format("{0} and {1} must both implement IComparable", validationContext.DisplayName, OtherProperty));

                // compare the objects
                var result = Comparer.Default.Compare(value, other);

                switch (Criteria)
                {
                    case CompareValues.GreaterThan:
                        if (result &gt; 0)
                            return null;
                        break;
                    case CompareValues.LessThan:
                        if (result &lt; 0)
                            return null;
                        break;
                    case CompareValues.GreatThanOrEqualTo:
                        if (result &gt;= 0)
                            return null;
                        break;
                    case CompareValues.LessThanOrEqualTo:
                        if (result &lt;= 0)
                            return null;
                        break;
                }
            }

            // got this far must mean the items don't meet the comparison criteria
            return new ValidationResult(FormatErrorMessage(validationContext.DisplayName));
        }

        /// &lt;summary&gt;
        /// Applies formatting to an error message.
        /// &lt;/summary&gt;
        /// &lt;param name="name"&gt;The name to include in the error message&lt;/param&gt;
        /// &lt;returns&gt;&lt;/returns&gt;
        public override string FormatErrorMessage(string name)
        {
            return String.Format(CultureInfo.CurrentCulture, base.ErrorMessageString, name, OtherProperty, Criteria.Description());
        }

        /// &lt;summary&gt;
        /// retrieve the object to compare to
        /// &lt;/summary&gt;
        /// &lt;returns&gt;&lt;/returns&gt;
        object GetOther(ValidationContext context)
        {
            return null;
        }
    }

    /// &lt;summary&gt;
    /// Indicates a comparison criteria used by the CompareValues attribute
    /// &lt;/summary&gt;
    public enum CompareValues
    {
        [Description("=")]
        EqualTo,
        [Description("!=")]
        NotEqualTo,
        [Description("&gt;")]
        GreaterThan,
        [Description("&lt;")]
        LessThan,
        [Description("&gt;=")]
        GreatThanOrEqualTo,
        [Description("&lt;=")]
        LessThanOrEqualTo
    }</code></pre>
<p>To use this attribute one would then just do:</p>
<pre class="prettyprint"><code>    /// &lt;summary&gt;
    /// Represents a booking
    /// &lt;/summary&gt;
    public class Booking : DomainObject&lt;int&gt;
    {
        /// &lt;summary&gt;
        /// The start of the booking
        /// &lt;/summary&gt;
        [Required]
        [CompareValues("End", CompareValues.LessThan)]
        public virtual DateTime? Start { get; set; }

        /// &lt;summary&gt;
        /// The end of the booking
        /// &lt;/summary&gt;
        [Required]
        public virtual DateTime? End { get; set; }
    }</code></pre>
]]></content:encoded>
			<wfw:commentRss>http://www.concurrentdevelopment.co.uk/blog/index.php/2011/01/custom-validationattribute-for-comparing-properties/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>LinkButtons, UpdatePanels and IDs</title>
		<link>http://www.concurrentdevelopment.co.uk/blog/index.php/2009/06/linkbuttons-updatepanels-and-ids/</link>
		<comments>http://www.concurrentdevelopment.co.uk/blog/index.php/2009/06/linkbuttons-updatepanels-and-ids/#comments</comments>
		<pubDate>Tue, 02 Jun 2009 09:10:41 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[ASP.NET]]></category>

		<guid isPermaLink="false">http://www.concurrentdevelopment.co.uk/blog/?p=6</guid>
		<description><![CDATA[I have an Repeater control sitting on my page, in the ItemTemplate of which are a couple of Button controls which do various things &#8211; delete the item, open the item&#8217;s detail pages etc&#8230; I think it would be nice to wrap the whole thing in an UpdatePanel to give it that whole AJAX-y feel. [...]]]></description>
			<content:encoded><![CDATA[<p>I have an Repeater control sitting on my page, in the ItemTemplate of which are a couple of Button controls which do various things &#8211; delete the item, open the item&#8217;s detail pages etc&#8230;  I think it would be nice to wrap the whole thing in an UpdatePanel to give it that whole AJAX-y feel.  All good.</p>
<p>Then the client asks if the buttons can be links instead of buttons.  No problem, think I, and go ahead and change the Buttons to LinkButtons.  At which point the application stops working. Clicking on the link buttons does a full post back (even though they&#8217;re in the UpdatePanel) and their associated methods in the code do not fire. Very strange.  I remove the UpdatePanel and the methods fire.  All very odd.</p>
<p>Now, I don&#8217;t like giving IDs to controls that I don&#8217;t reference directly in the code.  So as a matter of course I remove IDs from things like Buttons, LinkButtons etc&#8230;  Which is all fine until you put a LinkButton in an UpdatePanel &#8211; where an ID is necessary.</p>
<p>So, if you have a LinkButton within an UpdatePanel and it is doing an unexpected post back and the onclick event is not firing, check that you have an ID on it.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.concurrentdevelopment.co.uk/blog/index.php/2009/06/linkbuttons-updatepanels-and-ids/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

