<?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>Ian Mercer &#187; MVC</title>
	<atom:link href="http://blog.abodit.com/tag/mvc/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.abodit.com</link>
	<description>Living in the World&#039;s Smartest House</description>
	<lastBuildDate>Sat, 07 Jan 2012 19:50:56 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>Putting a feedback button on every page with ASP.NET MVC and JQuery</title>
		<link>http://blog.abodit.com/2010/03/feedback-button-asp-net-mvc-jquery/</link>
		<comments>http://blog.abodit.com/2010/03/feedback-button-asp-net-mvc-jquery/#comments</comments>
		<pubDate>Sat, 13 Mar 2010 08:57:52 +0000</pubDate>
		<dc:creator>Ian Mercer</dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[CSS]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[MVC]]></category>
		<category><![CDATA[UI]]></category>

		<guid isPermaLink="false">http://blog.abodit.com/?p=613</guid>
		<description><![CDATA[You&#8217;ve probably seen many web sites with the floating &#8216;feedback&#8217; button down the side. Here&#8217;s how to add one to your site using jQuery, jQuery UI and ASP.NET MVC. First make sure you have jQuery and jQuery UI referenced in your master page view together with the CSS file for whichever jQuery UI theme you <a href="http://blog.abodit.com/2010/03/feedback-button-asp-net-mvc-jquery/" class="more-link">More &#62;</a>]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.abodit.com/wp-content/uploads/2010/03/FeedbackButton.png"><img src="http://blog.abodit.com/wp-content/uploads/2010/03/FeedbackButton.png" alt="Feedback button" title="Feedback Button" width="233" height="629" class="alignright size-full wp-image-616" /></a></p>
<p>You&#8217;ve probably seen many web sites with the floating &#8216;feedback&#8217; button down the side.  Here&#8217;s how to add one to your site using jQuery, jQuery UI and ASP.NET MVC.</p>
<p>First make sure you have jQuery and jQuery UI referenced in your master page view together with the CSS file for whichever jQuery UI theme you have chosen.</p>
<p>We&#8217;ll make a few changes to the master page view to add the pop-up feedback form, we&#8217;ll add an action on a controller to accept the feedback that is posted, and we&#8217;ll need a small amount of CSS.</p>
<p>So, after referencing those javascript files and the theme CSS, the first thing to do is to add the following HTML to the bottom of your master page view:</p>
<pre class="brush: xml; title: ; notranslate">
            &lt;div id=&quot;feedbackdialog&quot; style=&quot;width:300px; height:300px;text-align:left;&quot;&gt;
                &lt;p&gt;Your name and/or email: &lt;br /&gt;
                &lt;input type=&quot;text&quot; id=&quot;feedbackEmail&quot; name=&quot;feedbackEmail&quot; size=&quot;34&quot; value=&quot;&lt;%: this.Model.AccountEmailOrEmpty %&gt;&quot; /&gt;
                &lt;/p&gt;
                &lt;p&gt;Comment:&lt;br /&gt;
                &lt;textarea id=&quot;feedbackComment&quot; name=&quot;comment&quot; cols=&quot;35&quot; rows=&quot;5&quot;&gt;&lt;/textarea&gt;&lt;/p&gt;
                &lt;br /&gt;
                &lt;div id=&quot;feedbackResult&quot;&gt;&lt;/div&gt;
            &lt;/div&gt;
</pre>
<p>Now add this code to your global javascript file that also referenced from your master page view &#8230; don&#8217;t embed it in the page, go ahead and do the right thing and put it in a .js file so it&#8217;s not a burden on every page.</p>
<pre class="brush: jscript; title: ; notranslate">
//function for the feedback form
$(document).ready(
    function () {
        /* Create the feedback dialog */

        $(&quot;#feedbackdialog&quot;).dialog(
        {
            closeOnEscape: true,
            modal: true,
            autoOpen: false,
            resizable: false,
            title: 'Feedback',
            width: 400,
            buttons: { &quot;Send&quot;: function () {
                var dlg = $(this);
                $.post(&quot;/corporate/suggest&quot;,
                        {
                            email: dlg.find(&quot;input[name='feedbackEmail']&quot;).val(),
                            comment: dlg.find(&quot;#feedbackComment&quot;).val(),
                            url: document.location.href
                         },
                        function (data) {
                            dlg.dialog('close');
                        }
                );
                $(this).html(&quot;&lt;p id='feedBackSending'&gt;Sending&lt;/p&gt;&quot;).dialog({ buttons: {} });
            }
            }
        });

        $('.contact_us').click(function () {
            $(&quot;#feedbackdialog&quot;).dialog(&quot;open&quot;);
            return false;
        });
    });
</pre>
<p>Next we&#8217;ll add the action referenced here, in the example we used the url &#8216;/corporate/suggest&#8217; so, assuming you have a controller called CorporateController, add the following action to it &#8230;</p>
<pre class="brush: csharp; title: ; notranslate">
        public ActionResult Suggest (string email, string comment, string url)
        {
            if (!string.IsNullOrWhiteSpace(comment))
            {
                // here we will log the feedback to the database and/or send it in email
            }
            return View();
        }
</pre>
<p>Create a view for &#8216;Suggest&#8217;, it doesn&#8217;t matter what&#8217;s in it as we don&#8217;t use the result currently.</p>
<p>And, finally we need a bit of CSS for the feedback icon itself:</p>
<pre class="brush: css; title: ; notranslate">
/* Feedback tab */
#feedbackTab
{
	right:0;
    position:fixed;
    width:32px;
    height:150px;
    top: 150px;
    z-index:1;
}
</pre>
<p>The feedback button now floats on every page, 150px from the top and it&#8217;s glued to the right hand side.</p>
<p>Of course you&#8217;ll need your own feedback image, or feel free to borrow the one here:- <a href="http://www.signswift.com/images/feedback.png">http://www.signswift.com/images/feedback.png</a></p>
<p>So with that all in place, click the feedback button and a form like this should appear.  Fill the information in and send it to the server.  Note how we silently grab the url of the page too so we can see which page they were on when the submitted the feedback.</p>
<p><a href="http://blog.abodit.com/wp-content/uploads/2010/03/FeedbackForm.png"><img src="http://blog.abodit.com/wp-content/uploads/2010/03/FeedbackForm.png" alt="Feedback Form" title="Feedback Form" width="646" height="488" class="aligncenter size-full wp-image-623" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.abodit.com/2010/03/feedback-button-asp-net-mvc-jquery/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>ASP.NET MVC SEO &#8211; Solution Part 1</title>
		<link>http://blog.abodit.com/2010/03/asp-net-mvc-seo-solution-part-1/</link>
		<comments>http://blog.abodit.com/2010/03/asp-net-mvc-seo-solution-part-1/#comments</comments>
		<pubDate>Mon, 08 Mar 2010 05:43:29 +0000</pubDate>
		<dc:creator>Ian Mercer</dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[SEO]]></category>
		<category><![CDATA[ASP.NET]]></category>
		<category><![CDATA[MVC]]></category>

		<guid isPermaLink="false">http://blog.abodit.com/?p=533</guid>
		<description><![CDATA[In a previous post I explained some of the issues with ASP.NET MVC when trying to implement an SEO-optimized web site.  In this post I&#8217;ll begin to explore some possible solutions. Step 1: Master View &#8211; some additions First let&#8217;s make it easy to set the meta description, page title, meta keywords and canonical url by <a href="http://blog.abodit.com/2010/03/asp-net-mvc-seo-solution-part-1/" class="more-link">More &#62;</a>]]></description>
			<content:encoded><![CDATA[<p>In a previous post I explained some of the issues with ASP.NET MVC when trying to implement an SEO-optimized web site.  In this post I&#8217;ll begin to explore some possible solutions.</p>
<p><span style="line-height: 28px; font-size: 26px;">Step 1: Master View &#8211; some additions</span></p>
<p>First let&#8217;s make it easy to set the <code>meta description</code>, <code>page title</code>, <code>meta keywords</code> and <code>canonical url</code> by adding the following to the <code>head</code> section of the master view:</p>
<pre class="brush: csharp; title: ; notranslate">
&lt;head id=&quot;Head1&quot; runat=&quot;server&quot;&gt;

    &lt;title&gt;&lt;%=ViewData[&quot;PageTitle&quot;]%&gt;&lt;/title&gt;  &lt;%-- This gets wrapped here, so it sees a title tag and doesn't emit two --%&gt;
    &lt;%=ViewData[&quot;PageDescription&quot;]%&gt;           &lt;%-- These are wrapped elsewhere so they vanish if not set--%&gt;
    &lt;%=ViewData[&quot;PageKeywords&quot;]%&gt;              &lt;%-- These are wrapped elsewhere so they vanish if not set--%&gt;
    &lt;%=ViewData[&quot;CanonicalUrl&quot;]%&gt;              &lt;%-- These are wrapped elsewhere so they vanish if not set--%&gt;

    &lt;meta name=&quot;robots&quot; content=&quot;noodp&quot; /&gt;  &lt;%--Don't use Open Directory Project descriptions--%&gt;
</pre>
<p>Note how we are not wrapping the canonical URL, and meta tags around the ViewData here (even though it would be more correct to do so).  We do this so that when those tags are not present the entire tag disappears from the page instead of rendering a tag with an empty string in it.  For the title tag however, that&#8217;s universal so let&#8217;s do it &#8216;properly&#8217;.</p>
<p>In tomorrow&#8217;s post I&#8217;ll show how we can set the Canonical URL using an attribute.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.abodit.com/2010/03/asp-net-mvc-seo-solution-part-1/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>ASP.NET MVC meet SEO; SEO meet ASP.NET MVC</title>
		<link>http://blog.abodit.com/2010/03/asp-net-mvc-meet-seo-seo-meet-asp-net-mvc/</link>
		<comments>http://blog.abodit.com/2010/03/asp-net-mvc-meet-seo-seo-meet-asp-net-mvc/#comments</comments>
		<pubDate>Thu, 04 Mar 2010 00:13:51 +0000</pubDate>
		<dc:creator>Ian Mercer</dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[MVC]]></category>
		<category><![CDATA[SEO]]></category>
		<category><![CDATA[SEO with ASP.NET MVC]]></category>
		<category><![CDATA[ASP.NET]]></category>

		<guid isPermaLink="false">http://blog.abodit.com/?p=523</guid>
		<description><![CDATA[Whilst ASP.NET is clearly the best thing to hit .NET web development in a long-time it seems like the framework itself is somewhat challenged when it comes to SEO.   For starters the concept of a page has all but disappeared &#8211; sure you can have a ViewPage but there&#8217;s no code associated with it. <a href="http://blog.abodit.com/2010/03/asp-net-mvc-meet-seo-seo-meet-asp-net-mvc/" class="more-link">More &#62;</a>]]></description>
			<content:encoded><![CDATA[<p>Whilst ASP.NET is clearly the best thing to hit .NET web development in a long-time it seems like the framework itself is somewhat challenged when it comes to SEO.   For starters the concept of a page has all but disappeared &#8211; sure you can have a ViewPage but there&#8217;s no code associated with it.  And sure, you have ASP.NET Routing so you can do anything you like with routes but the catchall route {Controller}/{Action}/{id} is as much a liability as it is a benefit as it catches things you really didn&#8217;t want it to catch and generates routes you really didn&#8217;t want to generate all too easily.</p>
<p>Convention over configuration is nice and all that, but sometimes a bit of configuration is necessary to bring your house into order, especially when the convention doesn&#8217;t allow things you really want for SEO.</p>
<p>So let&#8217;s take a look at all the things we really want to be able to do when creating an SEO friendly web site and see how we can get ASP.NET MVC to handle them.</p>
<h2>For SEO we need:-</h2>
<p>1. The ability to define a <strong>canonical url</strong> for a page.  To use that canonical URL whenever we generate a route.  To include that canonical url in the page header to instruct search engines that this is the canonical url for that page.</p>
<p>2. The ability to define <strong>multiple alternate URLs</strong> for a page.   Plans change and your site changes too but you don&#8217;t want 404 errors, you want the user to land on the same page even if you changed the URL to improve its SEO keyword content for example.  Ideally you&#8217;d like to 301 redirect these <strong>legacy urls</strong> but having them at least display the right page and including the canonical url in the header for that page is good enough.</p>
<p>3. The ability to use <strong>hyphens in urls</strong>.  But since Controllers are classes and Actions are methods and the convention is to use them as parts of the URL this isn&#8217;t supported out of the box.</p>
<p>4. The ability to define <strong>title</strong>, <strong>meta description</strong> and <strong>meta keywords</strong> tags for a page in such a way that you can enforce rules around them such as requiring every public page to have a title tag, or ensuring that the length of the title tag is reasonable, or ensuring that your product name is on the end of every title tag.</p>
<p>5. The ability to build a <strong>sitemap.xml</strong> file that we can submit to Google or Bing containing every URL that we want them to index.</p>
<p>In my next few posts I&#8217;ll explain how we can overcome all of these shortcomings of ASP.NET MVC to create a great SEO-friendly web site.</p>
<p>Stay tuned!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.abodit.com/2010/03/asp-net-mvc-meet-seo-seo-meet-asp-net-mvc/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>ASP.NET MVC 2 and the Ambiguous Match Exception for Action methods with different signatures</title>
		<link>http://blog.abodit.com/2010/02/asp-net-mvc-ambiguous-match/</link>
		<comments>http://blog.abodit.com/2010/02/asp-net-mvc-ambiguous-match/#comments</comments>
		<pubDate>Wed, 17 Feb 2010 01:01:42 +0000</pubDate>
		<dc:creator>Ian Mercer</dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[MVC]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://blog.abodit.com/?p=439</guid>
		<description><![CDATA[Although you can use this technique to allow POST requests to a page avoiding a redirect this is now considered a bad practice from a usability perspective because if the user hits refresh they get the classic browser warning. You normally want to use a Post-Redirect-Get pattern: when you make a POST request, once the <a href="http://blog.abodit.com/2010/02/asp-net-mvc-ambiguous-match/" class="more-link">More &#62;</a>]]></description>
			<content:encoded><![CDATA[<div style="width:300px;float:right;font-size:90%;padding:20px;margin:0 10px;background-color:#fee;">
Although you can use this technique to allow POST requests to a page avoiding a redirect this is now considered a bad practice from a usability perspective because if the user hits refresh they get the classic browser warning.  You normally want to use a Post-Redirect-Get pattern: when you make a POST request, once the request completes you do a redirect so that a GET request is fired.  In this way when the user refreshes the page, the last GET request will be executed rather than the POST.  You can still use this technique to have two post methods with different parameters but the same name, but why bother if each is going to do a redirect anyway back to the page Action method?
</div>
<p>One frustration I have with ASP.NET MVC is that you can&#8217;t easily have two actions with the same name but with different parameters, e.g. <code>Index(int a, int b)</code>, and <code>Index (int a)</code>.  If you try this you will get an <code>AmbiguousMatchException</code> because it makes no attempt to match the form values with the method parameters to figure out which method you want to call.  Now you can decorate the <code>Index()</code> with <code>[AcceptVerbs(HttpVerbs.Get)]</code> so that it at least will not be competing for ASP.NET MVC&#8217;s attention during the form post but your other two index methods will still cause the exception.</p>
<p>Supposed you wanted a page /Home/Index that had two forms on it:-</p>
<p>&lt;%using (Html.BeginForm()) { %&gt;<br />
&lt;%=Html.TextBox(&#8220;a&#8221;) %&gt;<br />
&lt;input type=&#8221;submit&#8221; name=&#8221;submitOne&#8221; title=&#8221;click me&#8221; /&gt;<br />
&lt;%} %&gt;</p>
<p>&lt;%using (Html.BeginForm()) { %&gt;<br />
&lt;%=Html.TextBox(&#8220;a&#8221;) %&gt;<br />
&lt;%=Html.TextBox(&#8220;b&#8221;) %&gt;<br />
&lt;input type=&#8221;submit&#8221; name=&#8221;submitTwo&#8221; title=&#8221;click me&#8221; /&gt;<br />
&lt;%} %&gt;</p>
<p>What we&#8217;d like to do is be able to have three action methods, <code>Index()</code>, <code>Index(Int a)</code> and <code>Index (Int a, Int b)</code>.</p>
<p>So let&#8217;s define our action methods like that and add a filter attribute to them that will filter methods according to the posted values ignoring any for which there aren&#8217;t enough posted values to match the number of parameters or for which the parameter names don&#8217;t match.</p>
<div style="font-family: Courier New; font-size: 10pt; color: black; background: white;">
<p style="margin: 0px;"><span style="color: #2b91af;"> 30</span> <span style="color: gray;">///</span><span style="color: green;"> </span><span style="color: gray;">&lt;summary&gt;</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 31</span> <span style="color: gray;">///</span><span style="color: green;"> Post a single integer back to the form, but don&#8217;t allow url /Home/Index/23</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 32</span> <span style="color: gray;">///</span><span style="color: green;"> </span><span style="color: gray;">&lt;/summary&gt;</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 33</span> [<span style="color: #2b91af;">ParametersMatch</span>]</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 34</span> [<span style="color: #2b91af;">AcceptVerbs</span>(<span style="color: #2b91af;">HttpVerbs</span>.Post)]</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 35</span> <span style="color: blue;">public</span> <span style="color: #2b91af;">ActionResult</span> Index([<span style="color: #2b91af;">FormValue</span>]<span style="color: blue;">int</span> a)</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 36</span> {</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 37</span> ViewData[<span style="color: #a31515;">"Message"</span>] = <span style="color: #a31515;">&#8220;You supplied one value &#8220;</span> + a ;</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 38</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 39</span> <span style="color: blue;">return</span> View();</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 40</span> }</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 41</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 42</span> <span style="color: gray;">///</span><span style="color: green;"> </span><span style="color: gray;">&lt;summary&gt;</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 43</span> <span style="color: gray;">///</span><span style="color: green;"> Post two integers back to the form OR include two integers in the path</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 44</span> <span style="color: gray;">///</span><span style="color: green;"> </span><span style="color: gray;">&lt;/summary&gt;</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 45</span> [<span style="color: #2b91af;">ParametersMatch</span>]</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 46</span> [<span style="color: #2b91af;">AcceptVerbs</span>(<span style="color: #2b91af;">HttpVerbs</span>.Post | <span style="color: #2b91af;">HttpVerbs</span>.Get)]</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 47</span> <span style="color: blue;">public</span> <span style="color: #2b91af;">ActionResult</span> Index([<span style="color: #2b91af;">FormValue</span>]<span style="color: blue;">int</span> a, [<span style="color: #2b91af;">FormValue</span>]<span style="color: blue;">int</span> b)</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 48</span> {</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 49</span> ViewData[<span style="color: #a31515;">"Message"</span>] = <span style="color: #a31515;">&#8220;You supplied two values &#8220;</span> + a + <span style="color: #a31515;">&#8221; &#8220;</span> + b;</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 50</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 51</span> <span style="color: blue;">return</span> View();</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 52</span> }</p>
<p>
And finally, here&#8217;s the code that makes that possible: an attribute you can apply to a method parameter to indicate that you want it in the posted form, and an action filter that filters out any action methods that don&#8217;t match.</p>
<p>With this in place you can (i) avoid an unnecessary redirect and (ii) have actions with the same name but with different parameters.
</p>
</div>
<p>Create a new ActionFilter like this &#8230;</p>
<div style="font-family: Courier New; font-size: 10pt; color: black; background: white;">
<p style="margin: 0px;"><span style="color: #2b91af;"> 1</span> <span style="color: blue;">namespace</span> TestApplication.Controllers</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 2</span> {</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 3</span> <span style="color: blue;">using</span> System;</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 4</span> <span style="color: blue;">using</span> System.Collections.Generic;</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 5</span> <span style="color: blue;">using</span> System.Collections.ObjectModel;</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 6</span> <span style="color: blue;">using</span> System.Diagnostics.CodeAnalysis;</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 7</span> <span style="color: blue;">using</span> System.Linq;</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 8</span> <span style="color: blue;">using</span> System.Reflection;</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 9</span> <span style="color: blue;">using</span> System.Web.Mvc.Resources;</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 10</span> <span style="color: blue;">using</span> System.Web.Mvc;</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 11</span> <span style="color: blue;">using</span> System.Diagnostics;</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 12</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 13</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 14</span> <span style="color: gray;">///</span><span style="color: green;"> </span><span style="color: gray;">&lt;summary&gt;</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 15</span> <span style="color: gray;">///</span><span style="color: green;"> This attribute can be placed on a parameter of an action method that should be present on the URL in route data</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 16</span> <span style="color: gray;">///</span><span style="color: green;"> </span><span style="color: gray;">&lt;/summary&gt;</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 17</span> [<span style="color: #2b91af;">AttributeUsage</span>(<span style="color: #2b91af;">AttributeTargets</span>.Parameter, AllowMultiple=<span style="color: blue;">false</span>)]</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 18</span> <span style="color: blue;">public</span> <span style="color: blue;">sealed</span> <span style="color: blue;">class</span> <span style="color: #2b91af;">RouteValueAttribute</span> : <span style="color: #2b91af;">Attribute</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 19</span> {</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 20</span> <span style="color: blue;">public</span> RouteValueAttribute() { }</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 21</span> }</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 22</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 23</span> <span style="color: gray;">///</span><span style="color: green;"> </span><span style="color: gray;">&lt;summary&gt;</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 24</span> <span style="color: gray;">///</span><span style="color: green;"> This attribute can be placed on a parameter of an action method that should be present in FormData</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 25</span> <span style="color: gray;">///</span><span style="color: green;"> </span><span style="color: gray;">&lt;/summary&gt;</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 26</span> [<span style="color: #2b91af;">AttributeUsage</span>(<span style="color: #2b91af;">AttributeTargets</span>.Parameter, AllowMultiple = <span style="color: blue;">false</span>)]</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 27</span> <span style="color: blue;">public</span> <span style="color: blue;">sealed</span> <span style="color: blue;">class</span> <span style="color: #2b91af;">FormValueAttribute</span> : <span style="color: #2b91af;">Attribute</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 28</span> {</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 29</span> <span style="color: blue;">public</span> FormValueAttribute() { }</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 30</span> }</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 31</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 32</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 33</span> <span style="color: gray;">///</span><span style="color: green;"> </span><span style="color: gray;">&lt;summary&gt;</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 34</span> <span style="color: gray;">///</span><span style="color: green;"> Parameters Match Attribute allows you to specify that an action is only valid</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 35</span> <span style="color: gray;">///</span><span style="color: green;"> if it has the right number of parameters marked [RouteValue] or [FormValue] that match with the form data or route data</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 36</span> <span style="color: gray;">///</span><span style="color: green;"> </span><span style="color: gray;">&lt;/summary&gt;</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 37</span> <span style="color: gray;">///</span><span style="color: green;"> </span><span style="color: gray;">&lt;remarks&gt;</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 38</span> <span style="color: gray;">///</span><span style="color: green;"> This attribute allows you to have two actions with the SAME name distinguished by the values they accept according to the</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 39</span> <span style="color: gray;">///</span><span style="color: green;"> name of those values.  Does NOT handle complex types and bindings yet but could be easily adapted to do so.</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 40</span> <span style="color: gray;">///</span><span style="color: green;"> </span><span style="color: gray;">&lt;/remarks&gt;</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 41</span> [<span style="color: #2b91af;">AttributeUsage</span>(<span style="color: #2b91af;">AttributeTargets</span>.Method, AllowMultiple = <span style="color: blue;">false</span>, Inherited = <span style="color: blue;">true</span>)]</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 42</span> <span style="color: blue;">public</span> <span style="color: blue;">sealed</span> <span style="color: blue;">class</span> <span style="color: #2b91af;">ParametersMatchAttribute</span> : <span style="color: #2b91af;">ActionMethodSelectorAttribute</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 43</span> {</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 44</span> <span style="color: blue;">public</span> ParametersMatchAttribute() { }</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 45</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 46</span> <span style="color: blue;">public</span> <span style="color: blue;">override</span> <span style="color: blue;">bool</span> IsValidForRequest(<span style="color: #2b91af;">ControllerContext</span> controllerContext, <span style="color: #2b91af;">MethodInfo</span> methodInfo)</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 47</span> {</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 48</span> <span style="color: green;">// The Route values</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 49</span> <span style="color: #2b91af;">List</span>&lt;<span style="color: blue;">string</span>&gt; requestRouteValuesKeys = controllerContext.RouteData.Values.Where(v =&gt; !(v.Key == <span style="color: #a31515;">&#8220;controller&#8221;</span> || v.Key == <span style="color: #a31515;">&#8220;action&#8221;</span> || v.Key == <span style="color: #a31515;">&#8220;area&#8221;</span>)).Select(rv =&gt; rv.Key).ToList();</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 50</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 51</span> <span style="color: green;">// The Form values</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 52</span> <span style="color: blue;">var</span> form = controllerContext.HttpContext.Request.Form;</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 53</span> <span style="color: #2b91af;">List</span>&lt;<span style="color: blue;">string</span>&gt; requestFormValuesKeys = form.AllKeys.ToList();</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 54</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 55</span> <span style="color: green;">// The parameters this method expects</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 56</span> <span style="color: blue;">var</span> parameters = methodInfo.GetParameters();</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 57</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 58</span> <span style="color: green;">// Parameters from the method that we haven&#8217;t matched up against yet</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 59</span> <span style="color: blue;">var</span> parametersNotMatched = parameters.ToList();</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 60</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 61</span> <span style="color: green;">// each parameter of the method can be marked as a [RouteValue] or [FormValue] or both or nothing</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 62</span> <span style="color: blue;">foreach</span> (<span style="color: blue;">var</span> param <span style="color: blue;">in</span> parameters)</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 63</span> {</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 64</span> <span style="color: blue;">string</span> name = param.Name;</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 65</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 66</span> <span style="color: blue;">bool</span> isRouteParam = param.GetCustomAttributes(<span style="color: blue;">true</span>).Any(a =&gt; a <span style="color: blue;">is</span> <span style="color: #2b91af;">RouteValueAttribute</span>);</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 67</span> <span style="color: blue;">bool</span> isFormParam = param.GetCustomAttributes(<span style="color: blue;">true</span>).Any(a =&gt; a <span style="color: blue;">is</span> <span style="color: #2b91af;">FormValueAttribute</span>);</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 68</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 69</span> <span style="color: blue;">if</span> (isRouteParam &amp;&amp; requestRouteValuesKeys.Contains(name))</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 70</span> {</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 71</span> <span style="color: green;">// Route value matches parameter</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 72</span> requestRouteValuesKeys.Remove(name);</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 73</span> parametersNotMatched.Remove(param);</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 74</span> }</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 75</span> <span style="color: blue;">else</span> <span style="color: blue;">if</span> (isFormParam &amp;&amp; requestFormValuesKeys.Contains(name))</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 76</span> {</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 77</span> <span style="color: green;">// Form value matches method parameter</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 78</span> requestFormValuesKeys.Remove(name);</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 79</span> parametersNotMatched.Remove(param);</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 80</span> }</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 81</span> <span style="color: blue;">else</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 82</span> {</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 83</span> <span style="color: green;">// methodInfo parameter does not match a route value or a form value</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 84</span> <span style="color: #2b91af;">Debug</span>.WriteLine(methodInfo + <span style="color: #a31515;">&#8221; failed to match &#8220;</span> + param + <span style="color: #a31515;">&#8221; against either a RouteValue or a FormValue&#8221;</span>);</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 85</span> <span style="color: blue;">return</span> <span style="color: blue;">false</span>;</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 86</span> }</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 87</span> }</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 88</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 89</span> <span style="color: green;">// Having removed all the parameters of the method that are matched by either a route value or a form value</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 90</span> <span style="color: green;">// we are now left with all the parameters that do not match and all the route and form values that were not used</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 91</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 92</span> <span style="color: blue;">if</span> (parametersNotMatched.Count &gt; 0)</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 93</span> {</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 94</span> <span style="color: #2b91af;">Debug</span>.WriteLine(methodInfo + <span style="color: #a31515;">&#8221; &#8211; FAIL: has parameters left over not matched by route or form values&#8221;</span>);</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 95</span> <span style="color: blue;">return</span> <span style="color: blue;">false</span>;</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 96</span> }</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 97</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 98</span> <span style="color: blue;">if</span> (requestRouteValuesKeys.Count &gt; 0)</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 99</span> {</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 100</span> <span style="color: #2b91af;">Debug</span>.WriteLine(methodInfo + <span style="color: #a31515;">&#8221; &#8211; FAIL: Request has route values left that aren&#8217;t consumed&#8221;</span>);</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 101</span> <span style="color: blue;">return</span> <span style="color: blue;">false</span>;</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 102</span> }</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 103</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 104</span> <span style="color: blue;">if</span> (requestFormValuesKeys.Count &gt; 1)</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 105</span> {</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 106</span> <span style="color: #2b91af;">Debug</span>.WriteLine(methodInfo + <span style="color: #a31515;">&#8221; &#8211; FAIL : unmatched form values &#8220;</span> + <span style="color: blue;">string</span>.Join(<span style="color: #a31515;">&#8220;, &#8220;</span>, requestFormValuesKeys.ToArray()));</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 107</span> <span style="color: blue;">return</span> <span style="color: blue;">false</span>;</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 108</span> }</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 109</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 110</span> <span style="color: #2b91af;">Debug</span>.WriteLine(methodInfo + <span style="color: #a31515;">&#8221; &#8211; PASS &#8211; unmatched form values &#8220;</span> + <span style="color: blue;">string</span>.Join(<span style="color: #a31515;">&#8220;, &#8220;</span>, requestFormValuesKeys.ToArray()));</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 111</span> <span style="color: blue;">return</span> <span style="color: blue;">true</span>;</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 112</span> }</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 113</span> }</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 114</span> }</p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://blog.abodit.com/2010/02/asp-net-mvc-ambiguous-match/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Building sitemap.xml for SEO ASP.NET MVC</title>
		<link>http://blog.abodit.com/2010/02/sitemap-xml-asp-net-aspnet-mvc/</link>
		<comments>http://blog.abodit.com/2010/02/sitemap-xml-asp-net-aspnet-mvc/#comments</comments>
		<pubDate>Tue, 09 Feb 2010 23:30:58 +0000</pubDate>
		<dc:creator>Ian Mercer</dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[MVC]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[SEO]]></category>
		<category><![CDATA[SEO with ASP.NET MVC]]></category>
		<category><![CDATA[sitemap]]></category>

		<guid isPermaLink="false">http://blog.abodit.com/?p=423</guid>
		<description><![CDATA[Creating a sitemap.xml file for Google and other search engines can be accomplished in MVC using a simple ActionResult that returns the appropriate XML blog. The problem however is in generating the list of URLs to go into that sitemap.xml file. In ASP.NET MVC there is no distinction between an action method that is a <a href="http://blog.abodit.com/2010/02/sitemap-xml-asp-net-aspnet-mvc/" class="more-link">More &#62;</a>]]></description>
			<content:encoded><![CDATA[<p>Creating a sitemap.xml file for Google and other search engines can be accomplished in MVC using a simple ActionResult that returns the appropriate XML blog.  The problem however is in generating the list of URLs to go into that sitemap.xml file.</p>
<p>In ASP.NET MVC there is no distinction between an action method that is a page and one that is a service call.  To remedy that let&#8217;s create an ActionFilterAttribute that can be applied to any method to mark it as a page and to record the URL that we want that page to show up as in our sitemap:</p>
<div style="font-family: Courier New; font-size: 10pt; color: black; background: white;">
<p style="margin: 0px;"><span style="color: #2b91af;"> 1</span> <span style="color: gray;">///</span><span style="color: green;"> </span><span style="color: gray;">&lt;summary&gt;</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 2</span> <span style="color: gray;">///</span><span style="color: green;"> This attribute indicates that a method is an actual page and gives the data for it</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 3</span> <span style="color: gray;">///</span><span style="color: green;"> </span><span style="color: gray;">&lt;/summary&gt;</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 4</span> [<span style="color: #2b91af;">AttributeUsage</span>(<span style="color: #2b91af;">AttributeTargets</span>.Class | <span style="color: #2b91af;">AttributeTargets</span>.Method, Inherited = <span style="color: blue;">true</span>, AllowMultiple = <span style="color: blue;">false</span>)]</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 5</span> <span style="color: blue;">public</span> <span style="color: blue;">class</span> <span style="color: #2b91af;">MVCUrlAttribute</span> : <span style="color: #2b91af;">ActionFilterAttribute</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 6</span> {</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 7</span> <span style="color: blue;">public</span> <span style="color: blue;">string</span> Url { <span style="color: blue;">get</span>; <span style="color: blue;">private</span> <span style="color: blue;">set</span>; }</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 8</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 9</span> <span style="color: blue;">public</span> MVCUrlAttribute(<span style="color: blue;">string</span> url)</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 10</span> {</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 11</span> <span style="color: blue;">this</span>.Url = url;</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 12</span> }</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 13</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 14</span> <span style="color: blue;">public</span> <span style="color: blue;">override</span> <span style="color: blue;">void</span> OnResultExecuting(<span style="color: #2b91af;">ResultExecutingContext</span> filterContext)</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 15</span> {</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 16</span> <span style="color: blue;">string</span> fullyQualifiedUrl = filterContext.HttpContext.Request.Url.GetLeftPart(<span style="color: #2b91af;">UriPartial</span>.Authority) + <span style="color: blue;">this</span>.Url;</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 17</span> <span style="color: green;">// We build HTML here because we want the View to be easily able to include it without any conditionals</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 18</span> <span style="color: green;">// and because the ASP.NET WebForms view engine sometimes doesn&#8217;t subsitute &lt;% in certain head items</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 19</span> filterContext.Controller.ViewData[<span style="color: #a31515;">"CanonicalUrl"</span>] = <span style="color: #a31515;">@&#8221;&lt;link rel=&#8221;"canonical&#8221;" href=&#8221;"&#8221;</span> + fullyQualifiedUrl + <span style="color: #a31515;">&#8221; /&gt;&#8221;</span>;</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 20</span> <span style="color: blue;">base</span>.OnResultExecuting(filterContext);</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 21</span> }</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 22</span> }</p>
</div>
<p>You may wonder at this point why we can&#8217;t just use the Routing table to figure this out.  The issue is that multiple routes may map onto one page but we still want it to show up just once in the sitemap otherwise we will get slammed for duplicate content.  We also want to be able to mark each page with its canonical URL.</p>
<p>Now we can use reflection to find all of the &#8216;pages&#8217; in our ASP.NET MVC Application and then build a sitemap.xml file from them.</p>
<div style="font-family: Courier New; font-size: 10pt; color: black; background: white;">
<p style="margin: 0px;"><span style="color: #2b91af;"> 1</span> <span style="color: #2b91af;">List</span>&lt;<span style="color: blue;">string</span>&gt; allPageUrls = <span style="color: blue;">new</span> <span style="color: #2b91af;">List</span>&lt;<span style="color: blue;">string</span>&gt;();</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 2</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 3</span> <span style="color: green;">// Find all the MVC Routes</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 4</span> Log.Debug(<span style="color: #a31515;">&#8220;*** FINDING ALL MVC ROUTES MARKED FOR INCLUSION IN SITEMAP&#8221;</span>);</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 5</span> <span style="color: blue;">var</span> allControllers = <span style="color: #2b91af;">Assembly</span>.GetExecutingAssembly().GetTypes().Where(t =&gt; t.IsSubclassOf(<span style="color: blue;">typeof</span>(<span style="color: #2b91af;">Controller</span>)));</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 6</span> Log.DebugFormat(<span style="color: #a31515;">&#8220;Found {0} controllers&#8221;</span>, allControllers.Count());</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 7</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 8</span> <span style="color: blue;">foreach</span> (<span style="color: blue;">var</span> controllerType <span style="color: blue;">in</span> allControllers)</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 9</span> {</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 10</span> <span style="color: blue;">var</span> allPublicMethodsOnController = controllerType.GetMethods(<span style="color: #2b91af;">BindingFlags</span>.Public | <span style="color: #2b91af;">BindingFlags</span>.Instance);</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 11</span> Log.DebugFormat(<span style="color: #a31515;">&#8220;Found {0} public methods on {1}&#8221;</span>, allPublicMethodsOnController.Count(), controllerType.Name);</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 12</span></p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 13</span> <span style="color: blue;">foreach</span> (<span style="color: blue;">var</span> publicMethod <span style="color: blue;">in</span> allPublicMethodsOnController)</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 14</span> {</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 15</span> <span style="color: blue;">var</span> mvcurlattr = publicMethod.GetCustomAttributes(<span style="color: blue;">true</span>).OfType&lt;<span style="color: #2b91af;">MVCUrlAttribute</span>&gt;().FirstOrDefault();</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 16</span> <span style="color: blue;">if</span> (mvcurlattr != <span style="color: blue;">null</span>)</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 17</span> {</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 18</span> <span style="color: blue;">string</span> url = mvcurlattr.Url;</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 19</span> Log.Debug(<span style="color: #a31515;">&#8220;Found &#8220;</span> + controllerType.Name + <span style="color: #a31515;">&#8220;.&#8221;</span> + publicMethod.Name + <span style="color: #a31515;">&#8221; &lt;&#8211; &#8220;</span> + url);</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 20</span> allPageUrls.Add(url);</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 21</span> }</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 22</span> }</p>
<p style="margin: 0px;"><span style="color: #2b91af;"> 23</span> }</p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://blog.abodit.com/2010/02/sitemap-xml-asp-net-aspnet-mvc/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Issues combining ASP.NET MVC and ASP.NET Web Forms in the same application</title>
		<link>http://blog.abodit.com/2010/02/issues-combining-asp-net-mvc-and-asp-net-web-forms-in-the-same-application/</link>
		<comments>http://blog.abodit.com/2010/02/issues-combining-asp-net-mvc-and-asp-net-web-forms-in-the-same-application/#comments</comments>
		<pubDate>Sun, 07 Feb 2010 01:06:29 +0000</pubDate>
		<dc:creator>Ian Mercer</dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[MVC]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://blog.abodit.com/?p=405</guid>
		<description><![CDATA[Recently I started migrating an ASP.NET WebForms project to ASP.NET MVC.  Hoping to do this in phases I created a combined project that is both a webforms project and an MVC project. Routing allows some requests to go to the WebForms pages and some to go to the new MVC pages. Routing has also enabled <a href="http://blog.abodit.com/2010/02/issues-combining-asp-net-mvc-and-asp-net-web-forms-in-the-same-application/" class="more-link">More &#62;</a>]]></description>
			<content:encoded><![CDATA[<p>Recently I started migrating an ASP.NET WebForms project to ASP.NET MVC.  Hoping to do this in phases I created a combined project that is both a webforms project and an MVC project.</p>
<p>Routing allows some requests to go to the WebForms pages and some to go to the new MVC pages.</p>
<p>Routing has also enabled SEO friendly URLs for all pages.</p>
<p>Everything seemed to be working great until I added a form to an MVC page and the URL it decided to use for posting the results back was one of the ASPX pages instead of the page it should have been.  The issue was that routes added for the legacy ASPX pages were being picked up as matches for the route that was being requested.</p>
<p>This article was helpful in explaining how to configure routes to avoid this problem <a href="http://forums.asp.net/t/1484855.aspx">http://forums.asp.net/t/1484855.aspx</a> but I still had an issue with the root &#8220;/&#8221; Route which was being picked for every form I created.  So I changed the root route to this and now all is well.  Of course, changing the home page to an MVC Action would also have solved the issue but I&#8217;m not ready to flip it just yet.</p>
<div id="_mcePaste">
<div style="font-family: Courier New; font-size: 10pt; color: black; background: white;">
<p style="margin: 0px;"><span style="color: #2b91af;"> Route</span>(<span style="color: #a31515;">&#8220;&#8221;</span>,</p>
<p style="margin: 0px;"><span style="color: blue;">new</span> <span style="color: #2b91af;">RouteValueDictionary</span>(<span style="color: blue;">new</span> { Controller = <span style="color: #a31515;">&#8220;Dummy&#8221;</span>, Action = <span style="color: #a31515;">&#8220;Dummy&#8221;</span> }),</p>
<p style="margin: 0px;"><span style="color: blue;">new</span> <span style="color: #2b91af;">RouteValueDictionary</span>(<span style="color: blue;">new</span> { Controller = <span style="color: #a31515;">&#8220;Dummy&#8221;</span>, Action = <span style="color: #a31515;">&#8220;Dummy&#8221;</span> }),</p>
<p style="margin: 0px;">routeHandler);</p>
<p style="margin: 0px;">
</div>
</div>
]]></content:encoded>
			<wfw:commentRss>http://blog.abodit.com/2010/02/issues-combining-asp-net-mvc-and-asp-net-web-forms-in-the-same-application/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

