<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:blogChannel="http://backend.userland.com/blogChannelModule" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:pingback="http://madskills.com/public/xml/rss/module/pingback/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">
  <channel>
    <title>eWorld.UI - Matt Hawley</title>
    <description>Ramblings of Matt</description>
    <link>http://blog.eworldui.net/</link>
    <docs>http://www.rssboard.org/rss-specification</docs>
    <generator>BlogEngine.Net Syndication Generator 1.0.0.0 (http://dotnetblogengine.net/)</generator>
    <language>en-US</language>
    <blogChannel:blogRoll>http://blog.eworldui.net/opml.axd</blogChannel:blogRoll>
    <blogChannel:blink>http://blog.eworldui.net/syndication.axd</blogChannel:blink>
    <dc:creator>Matt Hawley</dc:creator>
    <dc:title>eWorld.UI - Matt Hawley</dc:title>
    <geo:lat>0.000000</geo:lat>
    <geo:long>0.000000</geo:long>
    <geo:lat>47.381989</geo:lat><geo:long>-122.035536</geo:long><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" href="http://feeds.feedburner.com/eworldui" type="application/rss+xml" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com" /><item>
      <title>WikiPlex v1.2 Released</title>
      <description>&lt;p&gt;It's been a few months since the last release of &lt;a href="http://wikiplex.codeplex.com/"&gt;WikiPlex&lt;/a&gt;, but I honestly have good reasons - paternity leave! This updated version has taken in a lot of user feedback and put it into action - so thank you for contributing ideas. Since the &lt;a href="http://blog.eworldui.net/post/2009/08/WikiPlex-v11-Released.aspx"&gt;last release&lt;/a&gt;, there's been a steady download of the binaries/source code on a day-to-day basis, and am very happy where it is in the ecosystem. &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Here's what you'll find in WikiPlex v1.2:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;&lt;b&gt;&lt;u&gt;Indentation Macro&lt;/u&gt;&lt;/b&gt; - This new macro adds support for blockquote indentation. Utilize it similar to the ordered/unordered list macros with the colon character. See this &lt;a href="http://wikiplex.codeplex.com/Wiki/View.aspx?title=Text%20Alignment"&gt;documentation&lt;/a&gt; for an example on how to use it. &lt;/li&gt;    &lt;li&gt;&lt;b&gt;&lt;u&gt;Silverlight Macro&lt;/u&gt;&lt;/b&gt; - This macro was updated to support:       &lt;ol&gt;       &lt;li&gt;Any type of height/width unit (px, pc, pt, em, %, etc). &lt;/li&gt;        &lt;li&gt;Require Silverlight 3 as the default. You can optionally revert back to Silverlight 2 with the version=2 parameter. &lt;/li&gt;        &lt;li&gt;Support for initialization parameters by supplying any additional key/value parameters in the macro &lt;/li&gt;     &lt;/ol&gt;   &lt;/li&gt;    &lt;li&gt;&lt;b&gt;&lt;u&gt;Video Macro&lt;/u&gt;&lt;/b&gt; - This macro was updated to support:       &lt;ol&gt;       &lt;li&gt;A height/width supporting any type (px, pc, pt, em %, etc) &lt;/li&gt;        &lt;li&gt;Videos will not auto-start by default. &lt;/li&gt;        &lt;li&gt;Soapbox support has been removed &lt;/li&gt;     &lt;/ol&gt;   &lt;/li&gt;    &lt;li&gt;&lt;b&gt;&lt;u&gt;Syntax Highlight Support&lt;/u&gt;&lt;/b&gt; - Two more languages have been included:       &lt;ol&gt;       &lt;li&gt;{code:c++} ...Your C++ Code... {code:c++} &lt;/li&gt;        &lt;li&gt;{code:java} ...Your Java Code... {code:java} &lt;/li&gt;     &lt;/ol&gt;   &lt;/li&gt;    &lt;li&gt;&lt;b&gt;&lt;u&gt;Updated Sample Application&lt;/u&gt;&lt;/b&gt; - A WebForms variant was added to the sample application. It can be found under the /WebForms directory. &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;Unfortunately, I didn't get around to documenting the API, but I've not heard of anyone commenting they can't figure it out - so maybe it'll still happen sometime in the future. As always, if you have any ideas for new macros or extensibility points, please post them in the issue tracker and I'll make sure to look at them!&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Now, go and &lt;a href="http://wikiplex.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=34162"&gt;download WikiPlex v1.2!&lt;/a&gt; Also, don't forget to follow me on Twitter &lt;a href="http://twitter.com/matthawley"&gt;@matthawley&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.dotnetkicks.com/kick/?url=http%3a%2f%2fblog.eworldui.net%2fpost%2f2009%2f10%2fWikiPlex-v12-Released.aspx"&gt;&lt;img border="0" alt="kick it on DotNetKicks.com" src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fblog.eworldui.net%2fpost%2f2009%2f10%2fWikiPlex-v12-Released.aspx" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/eworldui?a=5nVqTOscT_M:TTQjSAemLco:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/eworldui?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/eworldui?a=5nVqTOscT_M:TTQjSAemLco:G79ilh31hkQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/eworldui?d=G79ilh31hkQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/eworldui?a=5nVqTOscT_M:TTQjSAemLco:D7DqB2pKExk"&gt;&lt;img src="http://feeds.feedburner.com/~ff/eworldui?i=5nVqTOscT_M:TTQjSAemLco:D7DqB2pKExk" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/eworldui/~4/5nVqTOscT_M" height="1" width="1"/&gt;</description>
      <link>http://feedproxy.google.com/~r/eworldui/~3/5nVqTOscT_M/post.aspx</link>
      <author>matthaw</author>
      <comments>http://blog.eworldui.net/post/2009/10/WikiPlex-v12-Released.aspx#comment</comments>
      <guid isPermaLink="false">http://blog.eworldui.net/post.aspx?id=acca4c32-f050-48fe-b8b9-1d37046a4368</guid>
      <pubDate>Thu, 08 Oct 2009 13:46:43 -0800</pubDate>
      <category>.NET</category>
      <category>CodePlex</category>
      <category>Development</category>
      <category>Programming</category>
      <category>WikiPlex</category>
      <dc:publisher>matthaw</dc:publisher>
      <pingback:server>http://blog.eworldui.net/pingback.axd</pingback:server>
      <pingback:target>http://blog.eworldui.net/post.aspx?id=acca4c32-f050-48fe-b8b9-1d37046a4368</pingback:target>
      <slash:comments>15</slash:comments>
      <trackback:ping>http://blog.eworldui.net/trackback.axd?id=acca4c32-f050-48fe-b8b9-1d37046a4368</trackback:ping>
      <wfw:comment>http://blog.eworldui.net/post/2009/10/WikiPlex-v12-Released.aspx#comment</wfw:comment>
      <wfw:commentRss>http://blog.eworldui.net/syndication.axd?post=acca4c32-f050-48fe-b8b9-1d37046a4368</wfw:commentRss>
    <feedburner:origLink>http://blog.eworldui.net/post.aspx?id=acca4c32-f050-48fe-b8b9-1d37046a4368</feedburner:origLink></item>
    <item>
      <title>WikiPlex v1.1 Released</title>
      <description>&lt;p&gt;It's only been a few weeks since the v1.0 release, but a lot of work has gone into a new release of &lt;a href="http://www.codeplex.com"&gt;CodePlex's&lt;/a&gt; embeddable wiki engine, &lt;a href="http://wikiplex.codeplex.com/"&gt;WikiPlex&lt;/a&gt;. The time in between has not been without a few highlights, including (&lt;a href="http://wikiplex.codeplex.com/stats"&gt;detailed stats&lt;/a&gt;):&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Over &lt;strong&gt;&lt;u&gt;500 combined downloads&lt;/u&gt;&lt;/strong&gt; of the v1.0 engine and sample application &lt;/li&gt;    &lt;li&gt;Roughly &lt;strong&gt;&lt;u&gt;175 downloads&lt;/u&gt;&lt;/strong&gt; of the source code (not including SVN enlistments) &lt;/li&gt;    &lt;li&gt;Over &lt;strong&gt;&lt;u&gt;8000 page views / 2200 visits&lt;/u&gt;&lt;/strong&gt; of the project site &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;&lt;u&gt;SoftPedia&lt;/u&gt;&lt;/strong&gt; picking up WikiPlex (&lt;a href="http://news.softpedia.com/news/Download-WikiPlex-Free-Open-Source-Wiki-Engine-from-Microsoft-117936.shtml"&gt;Download WikiPlex Free Open Source Wiki Engine from Microsoft&lt;/a&gt;) &lt;/li&gt;    &lt;li&gt;WikiPlex being already integrated in several projects (&lt;a href="http://swiki.codeplex.com"&gt;SWiki&lt;/a&gt; / &lt;a href="http://www.dijksterhuis.nu/blog/2009/8/2/wikiplex-for-umbraco.aspx"&gt;Umbraco&lt;/a&gt;) &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;I didn't have a long-term plan for revamping the wiki engine (I actually still don't!), but I did have several focuses for the short term that I wanted to achieve, including Mono compatibility, refactoring the macro parsing to enable more extensibility into the engine, and general &amp;quot;clean-up&amp;quot; tasks that I've been wanting to do. So, what's new in v1.1?&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;&lt;strong&gt;&lt;u&gt;Mono Compatibility&lt;/u&gt;&lt;/strong&gt; - The WikiPlex source has been tested against the 2.4.2.1 release of &lt;a href="http://www.mono-project.com/"&gt;Mono&lt;/a&gt; running on Linux. The source cleanly compiles and runs the sample application (note: you do still have to setup your own database for this). The only remaining issues running the sample application on Mono are ASP.NET MVC / Mono bugs. &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;&lt;u&gt;Scope Augmenters&lt;/u&gt;&lt;/strong&gt; - Scope Augmenters allow changing the resulting scopes prior to rendering based on a macro mapping. Previously - the Table, Ordered List, and Unordered List scope augmentation were hard-coded into the MacroParser. With this release, you can now add your own augmenters to fully control the rendering of WikiPlex. &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;&lt;u&gt;Syndicated Feeds&lt;/u&gt;&lt;/strong&gt; - The entire WCF syndication API was removed in lieu of utilizing a simpler, customized syndication framework. The main reasons for this change included: Mono currently not supporting this API and supporting the odd Google Atom specification. Aside from these internal changes, the macro was expanded so that it now supports {rss:url=...}, {feed:url=...}, and {atom:url=...} matching. No matter which format you use, the renderer will still choose the appropriate syndication reader (ie, you can specify rss for an atom feed, and vice versa). &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;&lt;u&gt;Sample Download&lt;/u&gt;&lt;/strong&gt; - To be honest, I never opened the sample project from the .zip file, and so I never realized the state that it was in. Be it missing files, incorrect references, whatever - everything is fixed now! Along with that, several people have indicated that they didn't have SQL 2008 Express installed, so within the App_Data directory, there's a Wiki.sql file that you can execute on your local SQL server to create the sample tables/data (oh, and don't forget to change your connection string). &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;&lt;u&gt;Invalid Syntax Highlight Code Blocks&lt;/u&gt;&lt;/strong&gt; - Previously, if someone supplied a {code:xxx} block that didn't match any of the supported languages, their source code would not be formatted as code. In v1.1 this has been changed, as it'll fall back to the non-syntax highlighted display of the code if it cannot find the language. &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;&lt;u&gt;Namespace Cleanup&lt;/u&gt;&lt;/strong&gt; - This should only affect advanced users of the wiki engine. Below is a list of the changes:       &lt;ol&gt;       &lt;li&gt;ScopeName was moved from WikiPlex.Common to WikiPlex &lt;/li&gt;        &lt;li&gt;IXmlDocumentReader and XmlDocumentReader were moved from WikiPlex.Common to WikiPlex.Syndication &lt;/li&gt;     &lt;/ol&gt;   &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;One item that is still on my plate, is actually spending some time documenting the API and producing a help file. Hopefully, the API isn't too difficult to understand, but I realize that it's somewhat necessary when it comes to implementing the engine within your application. Regardless, I feel that the engine is pretty close to where it needs to be regarding usability and extensibility. If you have any ideas for new macros or extensibility points, please post them in the &lt;a href="http://wikiplex.codeplex.com/WorkItem/List.aspx"&gt;issue tracker&lt;/a&gt; and I'll make sure to look at them!&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;With that said, I give you &lt;a href="http://wikiplex.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=31144"&gt;WikiPlex v1.1&lt;/a&gt; (&lt;a href="http://wikiplex.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=31144"&gt;go and download it now!&lt;/a&gt;) Also, follow me on Twitter &lt;a href="http://twitter.com/matthawley"&gt;@matthawley&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.dotnetkicks.com/kick/?url=http%3a%2f%2fblog.eworldui.net%2fpost%2f2009%2f08%2fWikiPlex-v11-Released.aspx"&gt;&lt;img border="0" alt="kick it on DotNetKicks.com" src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fblog.eworldui.net%2fpost%2f2009%2f08%2fWikiPlex-v11-Released.aspx" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/eworldui?a=8z70L1KTvz0:c1eyzokQvkY:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/eworldui?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/eworldui?a=8z70L1KTvz0:c1eyzokQvkY:G79ilh31hkQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/eworldui?d=G79ilh31hkQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/eworldui?a=8z70L1KTvz0:c1eyzokQvkY:D7DqB2pKExk"&gt;&lt;img src="http://feeds.feedburner.com/~ff/eworldui?i=8z70L1KTvz0:c1eyzokQvkY:D7DqB2pKExk" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/eworldui/~4/8z70L1KTvz0" height="1" width="1"/&gt;</description>
      <link>http://feedproxy.google.com/~r/eworldui/~3/8z70L1KTvz0/post.aspx</link>
      <author>matthaw</author>
      <comments>http://blog.eworldui.net/post/2009/08/WikiPlex-v11-Released.aspx#comment</comments>
      <guid isPermaLink="false">http://blog.eworldui.net/post.aspx?id=349d28cc-d1e9-442c-ad98-659ab1db1968</guid>
      <pubDate>Tue, 04 Aug 2009 18:31:59 -0800</pubDate>
      <category>.NET</category>
      <category>CodePlex</category>
      <category>Development</category>
      <category>Programming</category>
      <category>WikiPlex</category>
      <dc:publisher>matthaw</dc:publisher>
      <pingback:server>http://blog.eworldui.net/pingback.axd</pingback:server>
      <pingback:target>http://blog.eworldui.net/post.aspx?id=349d28cc-d1e9-442c-ad98-659ab1db1968</pingback:target>
      <slash:comments>15</slash:comments>
      <trackback:ping>http://blog.eworldui.net/trackback.axd?id=349d28cc-d1e9-442c-ad98-659ab1db1968</trackback:ping>
      <wfw:comment>http://blog.eworldui.net/post/2009/08/WikiPlex-v11-Released.aspx#comment</wfw:comment>
      <wfw:commentRss>http://blog.eworldui.net/syndication.axd?post=349d28cc-d1e9-442c-ad98-659ab1db1968</wfw:commentRss>
    <feedburner:origLink>http://blog.eworldui.net/post.aspx?id=349d28cc-d1e9-442c-ad98-659ab1db1968</feedburner:origLink></item>
    <item>
      <title>Extending WikiPlex with Custom Renderers</title>
      <description>&lt;p&gt;Following up from my prior post on &lt;a href="http://blog.eworldui.net/post/2009/07/Extending-WikiPlex-with-Custom-Macros.aspx"&gt;Extending WikiPlex with Custom Macros&lt;/a&gt; it's now time to talk about creating custom renderers. When we left off, we had created our title link macro and registered it with &lt;a href="http://wikiplex.codeplex.com/"&gt;WikiPlex&lt;/a&gt;. If you had attempted to utilize the new macro in wiki content, you'd get the message "Cannot resolve macro, as no renderers were found." instead of a hyperlink. This was the expected behavior, because while you had identified your new scope via parsing, you were missing that critical link of turning the scope into actual content. Let's take a look at our scenario again to refresh what we're trying to achieve:&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;We would like to integrate WikiPlex into an existing application. The idea is to allow a user contributed area specifically for wiki content. The user should be allowed to use all out-of-the-box macros provided, but also have the ability to have inter-wiki links with the format of [Title of Page]. As you probably realized, there is currently no macro/renderer that will take that content and turn it into a inter-wiki link, so we'll have to extend WikiPlex adding this functionality.&lt;/p&gt; &lt;/blockquote&gt;  &lt;h5&gt;Create a Renderer&lt;/h5&gt;  &lt;p&gt;Creating a renderer is actually the easiest portion of defining new wiki syntaxes, as it's as complicated as you need to make it. Again, a renderer simply takes in a scope (which is a contextual identifier), processes the content, and returns new content. Let's get started - so in your solution, create a class called TitleLinkRenderer and extend it from WikiPlex.Formatting.IRenderer. You'll then implement the members it requires (Id, CanExpand and Expand). The Id value is simply a string that is used as a key for static renderer registration, so it should be unique (follow the same rule of thumb for naming as the macros).&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Next, you'll implement the CanExpand method. This method simply takes in a scope name and returns a boolean value indicating if this renderer can expand (or render) the scope successfully. As the formatter is processing all scopes, it goes through the list of renderers in the formatter and finds the first match that can expand that particular scope. There is no guarantee of the order of checking renderers, so always unregister a renderer you're overriding its implementation for. As you'll see below, the CanExpand method is fairly trivial, however should your renderer support a number of scopes, you'll need to change this code to include all of them.&lt;/p&gt;  &lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;bool&lt;/span&gt; CanExpand(&lt;span class="kwrd"&gt;string&lt;/span&gt; scopeName)
{
   &lt;span class="kwrd"&gt;return&lt;/span&gt; scopeName == WikiScopeName.WikiLink;
}&lt;/pre&gt;

&lt;p&gt;Next, you'll implement the Expand method. This method will take in a scope name, the related input from the wiki source, and html / attribute encoding functions. The reason we're passing in html / attribute encoding functions, is so that you can utilize a consistent encoding scheme across all of the renderers. Out of the box, WikiPlex uses HttpUtility.HtmlEncode and HttpUtility.HtmlAttributeEncode, but by creating &amp;amp; supplying your own formatter, you can change these to use another library (like AntiXss). As previously stated, rendering is as hard as you need it to be. In the sample application example, we're just rendering a link utilizing the ASP.NET MVC UrlHelper (which is supplied via the constructor).&lt;/p&gt;

&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;const&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; LinkFormat = &lt;span class="str"&gt;&amp;quot;&amp;lt;a href=\&amp;quot;{0}\&amp;quot;&amp;gt;{1}&amp;lt;/a&amp;gt;&amp;quot;&lt;/span&gt;;

&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; Expand(&lt;span class="kwrd"&gt;string&lt;/span&gt; scopeName, &lt;span class="kwrd"&gt;string&lt;/span&gt; input,
                     Func&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;, &lt;span class="kwrd"&gt;string&lt;/span&gt;&amp;gt; htmlEncode, 
                     Func&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;, &lt;span class="kwrd"&gt;string&lt;/span&gt;&amp;gt; attributeEncode)
{
   &lt;span class="kwrd"&gt;string&lt;/span&gt; url = urlHelper.RouteUrl(&lt;span class="str"&gt;&amp;quot;Default&amp;quot;&lt;/span&gt;, &lt;span class="kwrd"&gt;new&lt;/span&gt; { slug = SlugHelper.Generate(input) });
   &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt;.Format(LinkFormat, attributeEncode(url), htmlEncode(input));
}&lt;/pre&gt;

&lt;p&gt;And now you have created your renderer, however it will still not be picked up when rendering your wiki content as you need to register the renderer with WikiPlex.&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;h5&gt;Registering a Renderer&lt;/h5&gt;

&lt;p&gt;Just as registering a macro, you have a static and a dynamic way to register your renderers. If your renderer requires only static dependencies (or no external runtime dependencies), you should opt for statically registering your renderer. To do this, have the following code in your application startup method&lt;/p&gt;

&lt;pre class="csharpcode"&gt;Renderers.Register&amp;lt;TitleLinkRenderer&amp;gt;();&lt;/pre&gt;

&lt;p&gt;When you call the WikiEngine.Render("content"), it will automatically pick up all statically defined renderers and use them when formatting your scopes. As previously stated, if you have external runtime dependencies (like in our example), a little bit of extra work is required when calling WikiEngine.Render - as you'll need to pass in a MacroFormatter instead. However, if you utilize the overload to only take in a formatter, you'll need to union the statically defined renderers with yours.&lt;/p&gt;

&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;private&lt;/span&gt; MacroFormatter GetFormatter()
{
   var siteRenderers = &lt;span class="kwrd"&gt;new&lt;/span&gt; IRenderer[] {&lt;span class="kwrd"&gt;new&lt;/span&gt; TitleLinkRenderer(Url)};
   IEnumerable&amp;lt;IRenderer&amp;gt; allRenderers = Renderers.All.Union(siteRenderers);
   &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; MacroFormatter(allRenderers);
}&lt;/pre&gt;

&lt;p&gt;Now, when you call WikiEngine.Render, you'll utilize the overload that takes in an IFormatter as a parameter. After you've set all of this up, try re-loading your page and you should see your syntax of [Title Link] be converted into the html &amp;lt;a href="http://blog.eworldui.net/title-link"&amp;gt;Title Link&amp;lt;/a&amp;gt;.&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;h5&gt;Summary&lt;/h5&gt;

&lt;p&gt;You now have a new fully functioning macro syntax. Obviously, this example is trivial - but I guarantee if you embed WikiPlex into your application and need any cross-page linking, you'll utilize this macro &amp;amp; renderer. Again, the possibilities are endless with what you can do, so long as you have a syntax, regex, and rendering code - you can allow your users to simply include expansive macros.&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;Download &lt;a href="http://wikiplex.codeplex.com/"&gt;WikiPlex&lt;/a&gt; now!&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.dotnetkicks.com/kick/?url=http%3a%2f%2fblog.eworldui.net%2fpost%2f2009%2f07%2fExtending-WikiPlex-with-Custom-Renderers.aspx"&gt;&lt;img border="0" alt="kick it on DotNetKicks.com" src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fblog.eworldui.net%2fpost%2f2009%2f07%2fExtending-WikiPlex-with-Custom-Renderers.aspx" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/eworldui?a=7UW9M7IFhHg:Hm2cSIVn7z4:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/eworldui?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/eworldui?a=7UW9M7IFhHg:Hm2cSIVn7z4:G79ilh31hkQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/eworldui?d=G79ilh31hkQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/eworldui?a=7UW9M7IFhHg:Hm2cSIVn7z4:D7DqB2pKExk"&gt;&lt;img src="http://feeds.feedburner.com/~ff/eworldui?i=7UW9M7IFhHg:Hm2cSIVn7z4:D7DqB2pKExk" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/eworldui/~4/7UW9M7IFhHg" height="1" width="1"/&gt;</description>
      <link>http://feedproxy.google.com/~r/eworldui/~3/7UW9M7IFhHg/post.aspx</link>
      <author>matthaw</author>
      <comments>http://blog.eworldui.net/post/2009/07/Extending-WikiPlex-with-Custom-Renderers.aspx#comment</comments>
      <guid isPermaLink="false">http://blog.eworldui.net/post.aspx?id=96e8007d-b46e-44a5-aa20-7e4f26066b88</guid>
      <pubDate>Thu, 30 Jul 2009 13:22:27 -0800</pubDate>
      <category>.NET</category>
      <category>CodePlex</category>
      <category>WikiPlex</category>
      <category>Programming</category>
      <category>Development</category>
      <dc:publisher>matthaw</dc:publisher>
      <pingback:server>http://blog.eworldui.net/pingback.axd</pingback:server>
      <pingback:target>http://blog.eworldui.net/post.aspx?id=96e8007d-b46e-44a5-aa20-7e4f26066b88</pingback:target>
      <slash:comments>8</slash:comments>
      <trackback:ping>http://blog.eworldui.net/trackback.axd?id=96e8007d-b46e-44a5-aa20-7e4f26066b88</trackback:ping>
      <wfw:comment>http://blog.eworldui.net/post/2009/07/Extending-WikiPlex-with-Custom-Renderers.aspx#comment</wfw:comment>
      <wfw:commentRss>http://blog.eworldui.net/syndication.axd?post=96e8007d-b46e-44a5-aa20-7e4f26066b88</wfw:commentRss>
    <feedburner:origLink>http://blog.eworldui.net/post.aspx?id=96e8007d-b46e-44a5-aa20-7e4f26066b88</feedburner:origLink></item>
    <item>
      <title>Extending WikiPlex with Custom Macros</title>
      <description>&lt;p&gt;One of the very nice features of &lt;a href="http://wikiplex.codeplex.com/"&gt;WikiPlex&lt;/a&gt; is the ability to extend it to your hearts desire. The API is completely open, and the entry points off of WikiEngine are merely wrappers. This means that, if you really wanted to, you could create your own parser and formatter - but the majority of extending WikiPlex will be done via macros and renderers. A summary of the extension points include: &lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Macros encapsulate rules for matching segments of content. &lt;/li&gt;    &lt;li&gt;Macro rules are regular expressions that map matches to scopes. &lt;/li&gt;    &lt;li&gt;Scopes are contextual identifiers. &lt;/li&gt;    &lt;li&gt;Renderers take scopes and expand them into a HTML formatted representation of the macro. &lt;/li&gt; &lt;/ol&gt;  &lt;h5&gt;Scenario&lt;/h5&gt;  &lt;p&gt;We would like to integrate WikiPlex into an existing application. The idea is to allow a user contributed area specifically for wiki content. The user should be allowed to use all out-of-the-box macros provided, but also have the ability to have inter-wiki links with the format of [Title of Page]. As you probably realized, there is currently no macro/renderer that will take that content and turn it into a inter-wiki link, so we'll have to extend WikiPlex adding this functionality.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h5&gt;Create a Macro&lt;/h5&gt;  &lt;p&gt;When creating a macro, you're going to have to dust off that copy of RegexBuddy you probably don't have installed anymore. Why? Well, as previously stated, macro rules are regular expressions - and unless you're a regex guru, you won't be able to do this ad-hoc without a great tool. Let's get started - so in your solution, create a class called TitleLinkMacro, and extend it from WikiPlex.Compilation.Macros.IMacro. You'll then implement the members it requires (Id and Rules). The Id value is simply a string that is used as a key for static macro registration and macro compilation, so it should be unique (rule of thumb, give it the name of your class but with spaces). Now, it's time to define your macro rules.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;As you may have noticed, I kept &amp;quot;rule&amp;quot; plural. The reason, is that the majority of macros you will create need to have an initial &amp;quot;escaped&amp;quot; rule. This rule basically stops the regex from matching within code blocks, between curly braces, and possibly between square brackets. Since our macro utilizes square brackets, we'll use the escape rule of CurlyBraceEscape.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Next, you'll define your regex (with extreme caution!) utilizing capturing groups to identify scopes. If you take a look at the code, you may not think that the scope identification is zero based - don't be fooled, it really is! Identifying an index 0 scope indicates the full match for that rule. When creating your capturing groups, you can have any number, allowing for fine granularity when rendering. So, let's take a look at the sample project's macro's rules.&lt;/p&gt;  &lt;div class="csharpcode"&gt;   &lt;pre class="alt"&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; IList&amp;lt;MacroRule&amp;gt; {&lt;/pre&gt;

  &lt;pre&gt;   get {&lt;/pre&gt;

  &lt;pre class="alt"&gt;      &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; List&amp;lt;MacroRule&amp;gt; {&lt;/pre&gt;

  &lt;pre&gt;         &lt;span class="kwrd"&gt;new&lt;/span&gt; MacroRule(EscapeRegexPatterns.CurlyBraceEscape),&lt;/pre&gt;

  &lt;pre class="alt"&gt;         &lt;span class="kwrd"&gt;new&lt;/span&gt; MacroRule(&lt;span class="str"&gt;@&amp;quot;(?i)(\[)(?!\#|[a-z]+:)((?&amp;gt;[^\]]+))(\])&amp;quot;&lt;/span&gt;,&lt;/pre&gt;

  &lt;pre&gt;                 &lt;span class="kwrd"&gt;new&lt;/span&gt; Dictionary&amp;lt;&lt;span class="kwrd"&gt;int&lt;/span&gt;, &lt;span class="kwrd"&gt;string&lt;/span&gt;&amp;gt; {&lt;/pre&gt;

  &lt;pre class="alt"&gt;                    { 1, ScopeName.Remove },&lt;/pre&gt;

  &lt;pre&gt;                    { 2, WikiScopeName.WikiLink },&lt;/pre&gt;

  &lt;pre class="alt"&gt;                    { 3, ScopeName.Remove }&lt;/pre&gt;

  &lt;pre&gt;                 })&lt;/pre&gt;

  &lt;pre class="alt"&gt;      };&lt;/pre&gt;

  &lt;pre&gt;   }&lt;/pre&gt;

  &lt;pre class="alt"&gt;}&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;As you can see, the regular expression is indicating that I should match 3 scopes per overall match. The scope &amp;quot;Remove&amp;quot; does just that. It removes the captured content when rendering. The WikiLink scope name is one that was created specifically for the sample. For the non-regex savvy developer, the regex reads:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Use case insensitive matching from this point on &lt;/li&gt;

  &lt;li&gt;Match the character &amp;quot;[&amp;quot; &lt;/li&gt;

  &lt;li&gt;Match any character until &amp;quot;]&amp;quot; is found 
    &lt;ol&gt;
      &lt;li&gt;But do not match if the character is preceded 
        &lt;ol&gt;
          &lt;li&gt;by the &amp;quot;#&amp;quot; character &lt;/li&gt;

          &lt;li&gt;or by any character between a-z, one or more times, followed by a &amp;quot;:&amp;quot; character &lt;/li&gt;
        &lt;/ol&gt;
      &lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;

  &lt;li&gt;Match the character &amp;quot;]&amp;quot; &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Our scope to step matching then is&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Remove &amp;quot;[&amp;quot; &lt;/li&gt;

  &lt;li&gt;WikiLink any content &lt;/li&gt;

  &lt;li&gt;Remove &amp;quot;]&amp;quot; &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Defining macro rules is a fairly straight forward process, just keep in mind that the order of the macro rules is &lt;strong&gt;&lt;u&gt;important&lt;/u&gt;&lt;/strong&gt;! You should also realize that if you wish to allow nesting of rules (for example, italicize bolded text) the italics and bold macro rules cannot be apart of the same macro. This, again, is because the macro rules are combined to build a large regular expression - and each rule is treated as an &amp;quot;or&amp;quot; statement.&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;h5&gt;Registering a Macro&lt;/h5&gt;

&lt;p&gt;After you have created your macro, you need to register it with WikiPlex. You have two ways of doing this - statically and dynamically. When statically registering macros, you simply need to have the following code in your application startup method&lt;/p&gt;

&lt;pre class="csharpcode"&gt;Macros.Register&amp;lt;TitleLinkMacro&amp;gt;();&lt;/pre&gt;

&lt;p&gt;When you call the WikiEngine.Render(&amp;quot;content&amp;quot;), it will automatically pick up your macro, compile it, and use it when parsing the wiki content. Dynamically loading your macros is useful when you require a different set of macros to be executed than what is normally registered. For example, in CodePlex - we have a different set of allowed macros between editing a project's wiki content and editing your personal statement. Dynamically loading is achieved by utilizing one of the WikiEngine.Render overloads:&lt;/p&gt;

&lt;pre class="csharpcode"&gt;WikiEngine.Render(&lt;span class="str"&gt;&amp;quot;content&amp;quot;&lt;/span&gt;, &lt;span class="kwrd"&gt;new&lt;/span&gt; IMacro[] { &lt;span class="kwrd"&gt;new&lt;/span&gt; WikiTitleLinkMacro() });&lt;/pre&gt;

&lt;p&gt;The only caveat of this approach, is that it will &lt;strong&gt;&lt;u&gt;only&lt;/u&gt;&lt;/strong&gt; use that macro when parsing your wiki content.&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;h5&gt;Summary&lt;/h5&gt;

&lt;p&gt;This is just the tip of the extensibility for WikiPlex. Creating your own macro is a great. Simply be cautious of your regular expression as it could have negative side effects (catastrophic backtracking) that will bring your site to a screeching halt! In the next installment, we'll take this scenario to the next step by creating a renderer for your macro.&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;Download &lt;a href="http://wikiplex.codeplex.com/"&gt;WikiPlex&lt;/a&gt; now!&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.dotnetkicks.com/kick/?url=http%3a%2f%2fblog.eworldui.net%2fpost%2f2009%2f07%2fExtending-WikiPlex-with-Custom-Macros.aspx"&gt;&lt;img border="0" alt="kick it on DotNetKicks.com" src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fblog.eworldui.net%2fpost%2f2009%2f07%2fExtending-WikiPlex-with-Custom-Macros.aspx" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/eworldui?a=wC5IfSnVkL4:jq4-eIcIklg:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/eworldui?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/eworldui?a=wC5IfSnVkL4:jq4-eIcIklg:G79ilh31hkQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/eworldui?d=G79ilh31hkQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/eworldui?a=wC5IfSnVkL4:jq4-eIcIklg:D7DqB2pKExk"&gt;&lt;img src="http://feeds.feedburner.com/~ff/eworldui?i=wC5IfSnVkL4:jq4-eIcIklg:D7DqB2pKExk" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/eworldui/~4/wC5IfSnVkL4" height="1" width="1"/&gt;</description>
      <link>http://feedproxy.google.com/~r/eworldui/~3/wC5IfSnVkL4/post.aspx</link>
      <author>matthaw</author>
      <comments>http://blog.eworldui.net/post/2009/07/Extending-WikiPlex-with-Custom-Macros.aspx#comment</comments>
      <guid isPermaLink="false">http://blog.eworldui.net/post.aspx?id=18702841-321f-40e7-873e-ff44eb1fefdb</guid>
      <pubDate>Fri, 24 Jul 2009 18:47:58 -0800</pubDate>
      <category>.NET</category>
      <category>CodePlex</category>
      <category>WikiPlex</category>
      <dc:publisher>matthaw</dc:publisher>
      <pingback:server>http://blog.eworldui.net/pingback.axd</pingback:server>
      <pingback:target>http://blog.eworldui.net/post.aspx?id=18702841-321f-40e7-873e-ff44eb1fefdb</pingback:target>
      <slash:comments>15</slash:comments>
      <trackback:ping>http://blog.eworldui.net/trackback.axd?id=18702841-321f-40e7-873e-ff44eb1fefdb</trackback:ping>
      <wfw:comment>http://blog.eworldui.net/post/2009/07/Extending-WikiPlex-with-Custom-Macros.aspx#comment</wfw:comment>
      <wfw:commentRss>http://blog.eworldui.net/syndication.axd?post=18702841-321f-40e7-873e-ff44eb1fefdb</wfw:commentRss>
    <feedburner:origLink>http://blog.eworldui.net/post.aspx?id=18702841-321f-40e7-873e-ff44eb1fefdb</feedburner:origLink></item>
    <item>
      <title>WikiPlex &amp;ndash; An Embedded Wiki Engine</title>
      <description>&lt;h4&gt;What and Why?&lt;/h4&gt;  &lt;p&gt;I'd like to introduce you to &lt;a href="http://wikiplex.codeplex.com/"&gt;WikiPlex&lt;/a&gt;, which is &lt;a href="http://www.codeplex.com/"&gt;CodePlex's&lt;/a&gt; wiki engine that we have re-written and made open source under the MS-PL license. I'm also happy to announce that our &lt;a href="http://wikiplex.codeplex.com/Release/ProjectReleases.aspx"&gt;first public release is now available&lt;/a&gt;!&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;CodePlex previously had a decent wiki engine that was written eon's ago. On the average, that wiki engine worked relatively well, but had a very problematic performance bug that would cause rendering slowness occasionally. So, instead of attempting to fix the bug, we decided to re-write the entire thing with the intensions of making it available to everyone! This time, we chose a different approach for parsing the wiki markup (utilizing regular expressions) which has proven to give us a performance boost as well as a relatively simpler architecture!&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;The main question you may be asking yourself is - Why use &lt;a href="http://wikiplex.codeplex.com/"&gt;WikiPlex&lt;/a&gt; over a different solution? Here's the simple answer: WikiPlex is great if you already have a .NET application you'd like to embed a wiki interface into. Be it as simple as allowing users to host their own homepage content, item descriptions, or comments - the possibilities are endless! &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h4&gt;Usage&lt;/h4&gt;  &lt;p&gt;&lt;a href="http://wikiplex.codeplex.com/"&gt;WikiPlex&lt;/a&gt; was built in a way that it can easily be added into your infrastructure. Whether your using dependency injection or not, the code is as simple as the following:&lt;/p&gt;  &lt;div style="color: black"&gt;   &lt;pre&gt;&lt;span style="color: blue"&gt;var&lt;/span&gt; engine = &lt;span style="color: blue"&gt;new&lt;/span&gt; WikiPlex.WikiEngine();
&lt;span style="color: blue"&gt;string&lt;/span&gt; output = engine.Render(&lt;span style="color: #a31515"&gt;&amp;quot;This is my wiki source!&amp;quot;&lt;/span&gt;);&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;If you take a look at the overloads for Render, you'll see that you have a lot of flexibility as far as rendering various wiki segments differently at runtime. (I'll describe the extensibility in the future)&lt;/p&gt;

&lt;div style="color: black"&gt;
  &lt;pre&gt;&lt;span style="color: blue"&gt;public&lt;/span&gt; &lt;span style="color: blue"&gt;interface&lt;/span&gt;&lt;span style="color: mediumturquoise"&gt; IWikiEngine
&lt;/span&gt;{
   &lt;span style="color: blue"&gt;string&lt;/span&gt; Render(&lt;span style="color: blue"&gt;string&lt;/span&gt; wikiContent);
   &lt;span style="color: blue"&gt;string&lt;/span&gt; Render(&lt;span style="color: blue"&gt;string&lt;/span&gt; wikiContent, IFormatter formatter);
   &lt;span style="color: blue"&gt;string&lt;/span&gt; Render(&lt;span style="color: blue"&gt;string&lt;/span&gt; wikiContent, IEnumerable&amp;lt;IMacro&amp;gt; macros);
   &lt;span style="color: blue"&gt;string&lt;/span&gt; Render(&lt;span style="color: blue"&gt;string&lt;/span&gt; wikiContent, IEnumerable&amp;lt;IMacro&amp;gt; macros, IFormatter formatter);
}&lt;/pre&gt;
&lt;/div&gt;

&lt;h4&gt;Supported Macros&lt;/h4&gt;

&lt;p&gt;The following are the macros supported out of the box for &lt;a href="http://wikiplex.codeplex.com/"&gt;WikiPlex&lt;/a&gt;. If you'd like to see the description and usage, please visit the &lt;a href="http://wikiplex.codeplex.com/Wiki/View.aspx?title=Markup%20Guide"&gt;markup guide&lt;/a&gt;.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Text Formatting 
    &lt;ul&gt;
      &lt;li&gt;Bold &lt;/li&gt;

      &lt;li&gt;Italics &lt;/li&gt;

      &lt;li&gt;Underline &lt;/li&gt;

      &lt;li&gt;Strikethrough &lt;/li&gt;

      &lt;li&gt;Superscript &lt;/li&gt;

      &lt;li&gt;Subscript &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;

  &lt;li&gt;Headings &lt;/li&gt;

  &lt;li&gt;Images &lt;/li&gt;

  &lt;li&gt;Links &lt;/li&gt;

  &lt;li&gt;Tables &lt;/li&gt;

  &lt;li&gt;Left and Right Aligned Text &lt;/li&gt;

  &lt;li&gt;Ordered and Unordered Lists &lt;/li&gt;

  &lt;li&gt;RSS / Atom Feeds &lt;/li&gt;

  &lt;li&gt;Source Code Blocks (both syntax highlighted and not) &lt;/li&gt;

  &lt;li&gt;Silverlight &lt;/li&gt;

  &lt;li&gt;Videos (Flash, Quicktime, Real, Soapbox, Windows Media, and YouTube) &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Enjoy! And don't forget to &lt;a href="http://wikiplex.codeplex.com/Release/ProjectReleases.aspx"&gt;download WikiPlex now&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.dotnetkicks.com/kick/?url=http%3a%2f%2fblog.eworldui.net%2fpost%2f2009%2f07%2fWikiPlex-ndash3b-An-Embedded-Wiki-Engine.aspx"&gt;&lt;img border="0" alt="kick it on DotNetKicks.com" src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fblog.eworldui.net%2fpost%2f2009%2f07%2fWikiPlex-ndash3b-An-Embedded-Wiki-Engine.aspx" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/eworldui?a=K8DpH2dEfbw:_OdhzbVc-Js:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/eworldui?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/eworldui?a=K8DpH2dEfbw:_OdhzbVc-Js:G79ilh31hkQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/eworldui?d=G79ilh31hkQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/eworldui?a=K8DpH2dEfbw:_OdhzbVc-Js:D7DqB2pKExk"&gt;&lt;img src="http://feeds.feedburner.com/~ff/eworldui?i=K8DpH2dEfbw:_OdhzbVc-Js:D7DqB2pKExk" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/eworldui/~4/K8DpH2dEfbw" height="1" width="1"/&gt;</description>
      <link>http://feedproxy.google.com/~r/eworldui/~3/K8DpH2dEfbw/post.aspx</link>
      <author>matthaw</author>
      <comments>http://blog.eworldui.net/post/2009/07/WikiPlex-ndash3b-An-Embedded-Wiki-Engine.aspx#comment</comments>
      <guid isPermaLink="false">http://blog.eworldui.net/post.aspx?id=58264690-ea26-468f-848b-b8f7001e8332</guid>
      <pubDate>Thu, 16 Jul 2009 11:04:57 -0800</pubDate>
      <category>.NET</category>
      <category>CodePlex</category>
      <category>Programming</category>
      <category>WikiPlex</category>
      <dc:publisher>matthaw</dc:publisher>
      <pingback:server>http://blog.eworldui.net/pingback.axd</pingback:server>
      <pingback:target>http://blog.eworldui.net/post.aspx?id=58264690-ea26-468f-848b-b8f7001e8332</pingback:target>
      <slash:comments>19</slash:comments>
      <trackback:ping>http://blog.eworldui.net/trackback.axd?id=58264690-ea26-468f-848b-b8f7001e8332</trackback:ping>
      <wfw:comment>http://blog.eworldui.net/post/2009/07/WikiPlex-ndash3b-An-Embedded-Wiki-Engine.aspx#comment</wfw:comment>
      <wfw:commentRss>http://blog.eworldui.net/syndication.axd?post=58264690-ea26-468f-848b-b8f7001e8332</wfw:commentRss>
    <feedburner:origLink>http://blog.eworldui.net/post.aspx?id=58264690-ea26-468f-848b-b8f7001e8332</feedburner:origLink></item>
    <item>
      <title>MEF + Factories Using an Export Provider</title>
      <description>&lt;p&gt;After my last post about &lt;a href="http://blog.eworldui.net/post/2008/11/MEF-2b-Factories.aspx"&gt;MEF + Factories&lt;/a&gt;, I was chatting with &lt;a href="http://blogs.msdn.com/gblock/"&gt;Glenn Block&lt;/a&gt; (PM for MEF) about my approach. One of the first things he mentioned is why I hadn't used an ExportProvider. As you know, ExportProvider's are new in the latest drop, and provide an interception point for resolving an import to an export. &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Taking a look back at the &lt;a href="http://www.codeplex.com/MEF/Wiki/View.aspx?title=Overview&amp;amp;referringTitle=Home"&gt;documentation&lt;/a&gt; on ComposablePart, I can see why Glenn mentioned this. In it, it states that a ComposoblePart must adhere to to Import/Export contracts. If you've looked at the prior example, you'll see that I'm explicitly violating that rule as I'm finding interfaces based on a base interface, not by Export! At this point, my mind started churning - mainly because there's not a lot of examples or descriptions of what an ExportProvider actually is - but because I wanted to do things "correctly" according to the framework provided. (As an aside, Glenn stated that a "What is an Export Provider" post or documentation is coming, maybe this'll boost that necessity!) What I ultimately came up with was a much cleaner solution than using a FactoryPartCatalog. &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Introducing FactoryExportProvider:&lt;/p&gt;  &lt;div class="csharpcode"&gt;   &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   1:  &lt;/span&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; FactoryExportProvider&amp;lt;T&amp;gt; : ExportProvider {&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   2:  &lt;/span&gt;   &lt;span class="kwrd"&gt;public&lt;/span&gt; FactoryExportProvider(Func&amp;lt;Type, T&amp;gt; resolutionMethod) { }&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   3:  &lt;/span&gt;   &lt;span class="kwrd"&gt;public&lt;/span&gt; FactoryExportProvider(Assembly assembly, Func&amp;lt;Type, T&amp;gt; resolutionMethod) { }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   4:  &lt;/span&gt;   &lt;span class="kwrd"&gt;public&lt;/span&gt; FactoryExportProvider(IEnumerable&amp;lt;Type&amp;gt; types, Func&amp;lt;Type, T&amp;gt; resolutionMethod { }&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   5:  &lt;/span&gt;}&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;What you'll see is again, it's very straight forward and provides a clean implementation in usage, just as the part catalog example did. Each constructor does just as it had done in the part catalog, so I'll not explain that again. One thing that I discussed with Glenn about was, is it appropriate to look for certain types within an Export Provider? His response was "absolutely you can do that". good, I think I've found the correct implementation, both from less code/object graph standpoint, but also from an intention standpoint.&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;Internally, the code is very simplistic. Since I'm finding these interfaces on-the-fly, and need more information than just the contract name, I needed to use a FactoryExportDefinition to store this information. I've you've looked at the prior example, you'll see this came back out of necessity.&lt;/p&gt;

&lt;div class="csharpcode"&gt;
  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   1:  &lt;/span&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; FactoryExportDefinition&amp;lt;T&amp;gt; : ExportDefinition {&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   2:  &lt;/span&gt;   &lt;span class="kwrd"&gt;public&lt;/span&gt; FactoryExportDefinition(&lt;span class="kwrd"&gt;string&lt;/span&gt; contractName, Type type, Func&amp;lt;Type, T&amp;gt; resolutionMethod) { }&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   3:  &lt;/span&gt;&amp;#160;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   4:  &lt;/span&gt;   &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; ContractName { get { ... } }&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   5:  &lt;/span&gt;   &lt;span class="kwrd"&gt;public&lt;/span&gt; Type ServiceType { get; &lt;span class="kwrd"&gt;private&lt;/span&gt; set; }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   6:  &lt;/span&gt;   &lt;span class="kwrd"&gt;public&lt;/span&gt; Func&amp;lt;Type, T&amp;gt; ResolutionMethod { get; &lt;span class="kwrd"&gt;private&lt;/span&gt; set; }&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   7:  &lt;/span&gt;}&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;When finding all of the interfaces that implement the base interface specified in the FactoryExportProvider, I convert those into a list of FactoryExportDefinition objects. Reason being, is that the export provider compares an ImportDefinition to an ExportDefinition when finding all available exports. This comparison is done by implementing the GetExportsCore method. The idea of export providers, is that when resolving all dependencies, MEF will call into all of the registered ExportProviders to determine if they can supply the Export and will do a bunch of cardinality matching for you. Out of the box, MEF provides an export provider for it's registered part catalogs. Here's the FactoryExportProvider's implementation of GetExportsCore.&lt;/p&gt;

&lt;div class="csharpcode"&gt;
  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   1:  &lt;/span&gt;&lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; IEnumerable&amp;lt;Export&amp;gt; GetExportsCore(ImportDefinition importDefinition) {&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   2:  &lt;/span&gt;   IList&amp;lt;Export&amp;gt; exports = &lt;span class="kwrd"&gt;new&lt;/span&gt; List&amp;lt;Export&amp;gt;();&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   3:  &lt;/span&gt;   var constraint = importDefinition.Constraint.Compile();&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   4:  &lt;/span&gt;   var foundExports = from d &lt;span class="kwrd"&gt;in&lt;/span&gt; definitions&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   5:  &lt;/span&gt;                      &lt;span class="kwrd"&gt;where&lt;/span&gt; constraint(d)&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   6:  &lt;/span&gt;                      select &lt;span class="kwrd"&gt;new&lt;/span&gt; Export(d, () =&amp;gt; d.ResolutionMethod(d.ServiceType));&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   7:  &lt;/span&gt;&amp;#160;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   8:  &lt;/span&gt;   &lt;span class="kwrd"&gt;if&lt;/span&gt; (importDefinition.Cardinality == ImportCardinality.ZeroOrMore)&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   9:  &lt;/span&gt;      exports = foundExports.ToList();&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  10:  &lt;/span&gt;   &lt;span class="kwrd"&gt;else&lt;/span&gt; &lt;span class="kwrd"&gt;if&lt;/span&gt; (foundExports.Count() == 1)&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  11:  &lt;/span&gt;      exports.Add(foundExports.First());&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  12:  &lt;/span&gt;&amp;#160;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  13:  &lt;/span&gt;   &lt;span class="kwrd"&gt;return&lt;/span&gt; exports;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  14:  &lt;/span&gt;}&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;It's that simple. The Export's that are returned will have the resolution method called when the actual object is needed. When it comes down to including this within your application, it's just as easy as it was for the part catalog, you just register things a bit differently.&lt;/p&gt;

&lt;div class="csharpcode"&gt;
  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   1:  &lt;/span&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;interface&lt;/span&gt; IService { }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   2:  &lt;/span&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;interface&lt;/span&gt; IUserService : IService { }&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   3:  &lt;/span&gt;&amp;#160;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   4:  &lt;/span&gt;[Export]&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   5:  &lt;/span&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; UserController {&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   6:  &lt;/span&gt;   [ImportingConstructor]&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   7:  &lt;/span&gt;   &lt;span class="kwrd"&gt;public&lt;/span&gt; UserController(IUserService userService) { }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   8:  &lt;/span&gt;}&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   9:  &lt;/span&gt;&amp;#160;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  10:  &lt;/span&gt;&lt;span class="rem"&gt;// in your application&lt;/span&gt;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  11:  &lt;/span&gt;&lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Compose() {&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  12:  &lt;/span&gt;   var catalog = &lt;span class="kwrd"&gt;new&lt;/span&gt; AttributedAssemblyPartCatalog(Assembly.GetExecutingAssembly());&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  13:  &lt;/span&gt;   var factoryProvider = &lt;span class="kwrd"&gt;new&lt;/span&gt; FactoryExportProvider&amp;lt;IService&amp;gt;(GetService);&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  14:  &lt;/span&gt;   var container = &lt;span class="kwrd"&gt;new&lt;/span&gt; CompositionContainer(catalog, factoryProvider);&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  15:  &lt;/span&gt;   container.AddPart(&lt;span class="kwrd"&gt;this&lt;/span&gt;);&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  16:  &lt;/span&gt;   container.Compose();&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  17:  &lt;/span&gt;}&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  18:  &lt;/span&gt;&amp;#160;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  19:  &lt;/span&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; IService GetService(Type type) { &lt;span class="kwrd"&gt;return&lt;/span&gt; ... }&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;And that's it. Ultimately, this leads to a cleaner implementation that uses less types that you have to manage, and, adheres to the correct intentions of the framework. Much thanks to Glenn who I chatted with for several hours last night! You can get the &lt;a href="http://www.eworldui.net/files/mefdemos/meffactoryexportprovider.zip" target="_blank"&gt;downloadable source here&lt;/a&gt;. Enjoy!&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.dotnetkicks.com/kick/?url=http%3a%2f%2fblog.eworldui.net%2fpost%2f2008%2f11%2fMEF-2b-Factories-Using-an-Export-Provider.aspx"&gt;&lt;img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fblog.eworldui.net%2fpost%2f2008%2f11%2fMEF-2b-Factories-Using-an-Export-Provider.aspx" border="0" alt="kick it on DotNetKicks.com" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/eworldui?a=zAHNSRtu-ys:5SCruR4-vNQ:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/eworldui?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/eworldui?a=zAHNSRtu-ys:5SCruR4-vNQ:D7DqB2pKExk"&gt;&lt;img src="http://feeds.feedburner.com/~ff/eworldui?i=zAHNSRtu-ys:5SCruR4-vNQ:D7DqB2pKExk" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/eworldui/~4/zAHNSRtu-ys" height="1" width="1"/&gt;</description>
      <link>http://feedproxy.google.com/~r/eworldui/~3/zAHNSRtu-ys/post.aspx</link>
      <author>matthaw</author>
      <comments>http://blog.eworldui.net/post/2008/11/MEF-2b-Factories-Using-an-Export-Provider.aspx#comment</comments>
      <guid isPermaLink="false">http://blog.eworldui.net/post.aspx?id=c305eabc-d5b7-4ae5-a17c-1e71a07819f8</guid>
      <pubDate>Sat, 29 Nov 2008 10:25:52 -0800</pubDate>
      <category>.NET</category>
      <category>MEF</category>
      <category>Programming</category>
      <dc:publisher>matthaw</dc:publisher>
      <pingback:server>http://blog.eworldui.net/pingback.axd</pingback:server>
      <pingback:target>http://blog.eworldui.net/post.aspx?id=c305eabc-d5b7-4ae5-a17c-1e71a07819f8</pingback:target>
      <slash:comments>74</slash:comments>
      <trackback:ping>http://blog.eworldui.net/trackback.axd?id=c305eabc-d5b7-4ae5-a17c-1e71a07819f8</trackback:ping>
      <wfw:comment>http://blog.eworldui.net/post/2008/11/MEF-2b-Factories-Using-an-Export-Provider.aspx#comment</wfw:comment>
      <wfw:commentRss>http://blog.eworldui.net/syndication.axd?post=c305eabc-d5b7-4ae5-a17c-1e71a07819f8</wfw:commentRss>
    <feedburner:origLink>http://blog.eworldui.net/post.aspx?id=c305eabc-d5b7-4ae5-a17c-1e71a07819f8</feedburner:origLink></item>
    <item>
      <title>MEF + Factories</title>
      <description>&lt;p&gt;Lately I've been really digging into &lt;a href="http://www.codeplex.com/mef"&gt;MEF&lt;/a&gt; and have been looking at it's pros &amp;amp; cons, ease of use, extensibility, and the simple DI container that it can provide. I'm not going to give an overview of MEF, as others have done so already. What I am here to show off is a concept that may prove useful for some applications. Many of us use a DI container in very simplistic ways, as well as registering injection strategies during type resolution. If you have no needs of this latter, MEF is very simple and easily fits into your current architecture by not having to change anything but decorating things. For example: &lt;/p&gt;  &lt;div class="csharpcode"&gt;   &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   1:  &lt;/span&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;interface&lt;/span&gt; IUserService { }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   2:  &lt;/span&gt;&amp;#160;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   3:  &lt;/span&gt;[Export(&lt;span class="kwrd"&gt;typeof&lt;/span&gt;(IUserService))]&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   4:  &lt;/span&gt;[CompositionOptions(CreationPolicy = CreationPolicy.Factory)]&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   5:  &lt;/span&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; UserService : IUserService { }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   6:  &lt;/span&gt;&amp;#160;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   7:  &lt;/span&gt;[Export]&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   8:  &lt;/span&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; UserController {&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   9:  &lt;/span&gt;   [ImportingConstructor]&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  10:  &lt;/span&gt;   &lt;span class="kwrd"&gt;public&lt;/span&gt; UserController(IUserService userService) { }&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  11:  &lt;/span&gt;}&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;At MEF's simplistic nature, you see that during construction, our exported services are being imported for us, but only because we don't care about it's construction and assume that generic construction will work. So when we call resolve UserController using MEF, it'll create and inject a new instance of UserService for us.&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;Now, say we have a need where the construction of IUserService needs to go through a factory. For instance, maybe IUserService is a WCF endpoint, and you have custom logic built into properly constructing the proxy endpoint. Well, MEF can solve this issue for you by exporting methods, but what you have to do is ultimately change your code and have 2 constructors.&lt;/p&gt;

&lt;div class="csharpcode"&gt;
  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   1:  &lt;/span&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;interface&lt;/span&gt; IUserService { }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   2:  &lt;/span&gt;&amp;#160;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   3:  &lt;/span&gt;&lt;span class="rem"&gt;// in your application&lt;/span&gt;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   4:  &lt;/span&gt;[Export(&lt;span class="kwrd"&gt;typeof&lt;/span&gt;(IUserService))]&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   5:  &lt;/span&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; IUserService ConstructUserService() { &lt;span class="kwrd"&gt;return&lt;/span&gt; ... }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   6:  &lt;/span&gt;&amp;#160;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   7:  &lt;/span&gt;[Export]&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   8:  &lt;/span&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; UserController {&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   9:  &lt;/span&gt;   [ImportingConstructor]&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  10:  &lt;/span&gt;   &lt;span class="kwrd"&gt;public&lt;/span&gt; UserController([Import(&lt;span class="kwrd"&gt;typeof&lt;/span&gt;(IUserService))] Func&amp;lt;IUserService&amp;gt; serviceMethod)&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  11:  &lt;/span&gt;       : &lt;span class="kwrd"&gt;this&lt;/span&gt;(serviceMethod())&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  12:  &lt;/span&gt;   { }&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  13:  &lt;/span&gt;&amp;#160;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  14:  &lt;/span&gt;   &lt;span class="kwrd"&gt;public&lt;/span&gt; UserController(IUserService userService) { }&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  15:  &lt;/span&gt;}&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;As you can see, it's not that nice. We need both constructors because one is used in production and one is used for testability. It ultimately leads to a lot of confusion as to why we need it. So, with that in mind, I set out to determine how this pattern could be achieved using MEF, but also provide a seamless transition from a DI world to MEF. Enter, FactoryPartCatalog:&lt;/p&gt;

&lt;div class="csharpcode"&gt;
  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   1:  &lt;/span&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; FactoryPartCatalog&amp;lt;T&amp;gt; : ComposablePartCatalog {&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   2:  &lt;/span&gt;   &lt;span class="kwrd"&gt;public&lt;/span&gt; FactoryPartCatalog(Func&amp;lt;Type, T&amp;gt; resolutionMethod) { }&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   3:  &lt;/span&gt;   &lt;span class="kwrd"&gt;public&lt;/span&gt; FactoryPartCatalog(Assembly assembly, Func&amp;lt;Type, T&amp;gt; resolutionMethod) { }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   4:  &lt;/span&gt;   &lt;span class="kwrd"&gt;public&lt;/span&gt; FactoryPartCatalog(IEnumerable&amp;lt;Type&amp;gt; types, Func&amp;lt;Type, T&amp;gt; resolutionMethod) { }&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   5:  &lt;/span&gt;&amp;#160;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   6:  &lt;/span&gt;   &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; IQueryable&amp;lt;ComposableDefinition&amp;gt; Parts { get { &lt;span class="kwrd"&gt;return&lt;/span&gt; ... } }&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   7:  &lt;/span&gt;}&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;When we use this in our application, it brings back the simplicity of MEF. What it's doing during construction is looking through the assembly (first two constructors) to find all interfaces that implement type T. The interfaces that it finds will be created into ComposablePart's for MEF's container to utilize. Ultimately, when GetExportedObject&amp;lt;T&amp;gt; is called, it'll execute the resolution method you specified passing in the Type that was requested.&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;As you can see below, we're using a AggregatingComposablePartCatalog adding our new FactoryPartCatalog and AttributedAssemblyPartCatalog. We've told FactoryPartCatalog to look through the current assembly for all interfaces that derive from IService. Upon construction injection by MEF, it'll find that it's requesting an export of IUserService, find it in the FactoryPartCatalog, and call GetService(Type) to get it's instance.&lt;/p&gt;

&lt;div class="csharpcode"&gt;
  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   1:  &lt;/span&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;interface&lt;/span&gt; IService { }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   2:  &lt;/span&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;interface&lt;/span&gt; IUserService : IService { }&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   3:  &lt;/span&gt;&amp;#160;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   4:  &lt;/span&gt;[Export]&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   5:  &lt;/span&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; UserController {&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   6:  &lt;/span&gt;   [ImportingConstructor]&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   7:  &lt;/span&gt;   &lt;span class="kwrd"&gt;public&lt;/span&gt; UserController(IUserService userService) { }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   8:  &lt;/span&gt;}&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   9:  &lt;/span&gt;&amp;#160;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  10:  &lt;/span&gt;&lt;span class="rem"&gt;// in your application&lt;/span&gt;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  11:  &lt;/span&gt;&lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Compose() {&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  12:  &lt;/span&gt;   var catalog = AggregatingComposablePartCatalog();&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  13:  &lt;/span&gt;   catalog.Catalogs.Add(&lt;span class="kwrd"&gt;new&lt;/span&gt; AttributedAssemblyPartCatalog(Assembly.GetExecutingAssembly()));&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  14:  &lt;/span&gt;   catalog.Catalogs.Add(&lt;span class="kwrd"&gt;new&lt;/span&gt; FactoryPartCatalog&amp;lt;IService&amp;gt;(GetService);&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  15:  &lt;/span&gt;   var container = &lt;span class="kwrd"&gt;new&lt;/span&gt; CompositionContainer(catalog);&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  16:  &lt;/span&gt;   container.AddPart(&lt;span class="kwrd"&gt;this&lt;/span&gt;);&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  17:  &lt;/span&gt;   container.Compose();&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  18:  &lt;/span&gt;}&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  19:  &lt;/span&gt;&amp;#160;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  20:  &lt;/span&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; IService GetService(Type type) { &lt;span class="kwrd"&gt;return&lt;/span&gt; ... }&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Now, there's a lot more code behind the scenes that is required to get a new Part Catalog up and running, but I'll leave that for you to check out in the &lt;a href="http://www.eworldui.net/files/mefdemos/meffactorypartcatalog.zip"&gt;downloadable source&lt;/a&gt;. As this is purely a proof of concept, I'm sure there's more simplifications or additions that can be added, but for getting this running out of the box in this manner, it works great!&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.dotnetkicks.com/kick/?url=http%3a%2f%2fblog.eworldui.net%2fpost.aspx%3fid%3dbcdae64d-f1b7-40f6-8a96-076cc5767fa0"&gt;&lt;img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fblog.eworldui.net%2fpost.aspx%3fid%3dbcdae64d-f1b7-40f6-8a96-076cc5767fa0" border="0" alt="kick it on DotNetKicks.com" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/eworldui?a=WBhoaNk_uG0:tuwnKoJCx00:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/eworldui?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/eworldui?a=WBhoaNk_uG0:tuwnKoJCx00:D7DqB2pKExk"&gt;&lt;img src="http://feeds.feedburner.com/~ff/eworldui?i=WBhoaNk_uG0:tuwnKoJCx00:D7DqB2pKExk" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/eworldui/~4/WBhoaNk_uG0" height="1" width="1"/&gt;</description>
      <link>http://feedproxy.google.com/~r/eworldui/~3/WBhoaNk_uG0/post.aspx</link>
      <author>matthaw</author>
      <comments>http://blog.eworldui.net/post/2008/11/MEF-2b-Factories.aspx#comment</comments>
      <guid isPermaLink="false">http://blog.eworldui.net/post.aspx?id=bcdae64d-f1b7-40f6-8a96-076cc5767fa0</guid>
      <pubDate>Thu, 27 Nov 2008 13:47:31 -0800</pubDate>
      <category>.NET</category>
      <category>Development</category>
      <category>MEF</category>
      <dc:publisher>matthaw</dc:publisher>
      <pingback:server>http://blog.eworldui.net/pingback.axd</pingback:server>
      <pingback:target>http://blog.eworldui.net/post.aspx?id=bcdae64d-f1b7-40f6-8a96-076cc5767fa0</pingback:target>
      <slash:comments>53</slash:comments>
      <trackback:ping>http://blog.eworldui.net/trackback.axd?id=bcdae64d-f1b7-40f6-8a96-076cc5767fa0</trackback:ping>
      <wfw:comment>http://blog.eworldui.net/post/2008/11/MEF-2b-Factories.aspx#comment</wfw:comment>
      <wfw:commentRss>http://blog.eworldui.net/syndication.axd?post=bcdae64d-f1b7-40f6-8a96-076cc5767fa0</wfw:commentRss>
    <feedburner:origLink>http://blog.eworldui.net/post.aspx?id=bcdae64d-f1b7-40f6-8a96-076cc5767fa0</feedburner:origLink></item>
    <item>
      <title>ASP.NET MVC: Simplified Localization via ViewEngines</title>
      <description>&lt;p&gt;Thanks to &lt;a href="http://bradwilson.typepad.com/"&gt;Brad&lt;/a&gt;, he identified a few areas that made things MUCH simpler from my &lt;a href="http://blog.eworldui.net/post/2008/10/ASPNET-MVC-Localization-via-View-Engines.aspx"&gt;prior implementation&lt;/a&gt;. Notably, while you still have your ViewEngine specify "here's your view's path" there's no longer a need for having a new helper, derived classes, etc. This implementation goes back to the simplified HtmlHelper extension in which you can use in any ViewEngine regardless. It also allows you to "replace" the implementation by just changing the namespace, just as you can do with Html and Ajax.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h4&gt;Simplified View Engine&lt;/h4&gt;  &lt;p&gt;As previously stated, you still need a new view engine and view, because this is the only point in which you can truly grab which view is being rendered. What's nice now, is that it has been simplified down to using the base implementation and only setting a ViewData field in which the Resource extension method picks up and uses.&lt;/p&gt;  &lt;div class="csharpcode"&gt;   &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   1:  &lt;/span&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; LocalizationWebFormViewEngine : WebFormViewEngine&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   2:  &lt;/span&gt;{&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   3:  &lt;/span&gt;    &lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; IView CreateView(ControllerContext controllerContext, &lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   4:  &lt;/span&gt;                                                &lt;span class="kwrd"&gt;string&lt;/span&gt; viewPath, &lt;span class="kwrd"&gt;string&lt;/span&gt; masterPath)&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   5:  &lt;/span&gt;    {&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   6:  &lt;/span&gt;        &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; LocalizationWebFormView(viewPath, masterPath);&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   7:  &lt;/span&gt;    }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   8:  &lt;/span&gt;&amp;#160;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   9:  &lt;/span&gt;    &lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; IView CreatePartialView(ControllerContext controllerContext, &lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  10:  &lt;/span&gt;                                                                          &lt;span class="kwrd"&gt;string&lt;/span&gt; partialPath)&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  11:  &lt;/span&gt;    {&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  12:  &lt;/span&gt;        &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; LocalizationWebFormView(partialPath, &lt;span class="kwrd"&gt;null&lt;/span&gt;);&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  13:  &lt;/span&gt;    }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  14:  &lt;/span&gt;}&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  15:  &lt;/span&gt;&amp;#160;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  16:  &lt;/span&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; LocalizationWebFormView : WebFormView&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  17:  &lt;/span&gt;{&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  18:  &lt;/span&gt;    &lt;span class="kwrd"&gt;internal&lt;/span&gt; &lt;span class="kwrd"&gt;const&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; ViewPathKey = &lt;span class="str"&gt;&amp;quot;__ViewPath__&amp;quot;&lt;/span&gt;;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  19:  &lt;/span&gt;&amp;#160;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  20:  &lt;/span&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; LocalizationWebFormView(&lt;span class="kwrd"&gt;string&lt;/span&gt; viewPath) : &lt;span class="kwrd"&gt;base&lt;/span&gt;(viewPath)&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  21:  &lt;/span&gt;    {&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  22:  &lt;/span&gt;    }&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  23:  &lt;/span&gt;&amp;#160;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  24:  &lt;/span&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; LocalizationWebFormView(&lt;span class="kwrd"&gt;string&lt;/span&gt; viewPath, &lt;span class="kwrd"&gt;string&lt;/span&gt; masterPath) &lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  25:  &lt;/span&gt;              : &lt;span class="kwrd"&gt;base&lt;/span&gt;(viewPath, masterPath)&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  26:  &lt;/span&gt;    {&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  27:  &lt;/span&gt;    }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  28:  &lt;/span&gt;&amp;#160;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  29:  &lt;/span&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Render(ViewContext viewContext, TextWriter writer)&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  30:  &lt;/span&gt;    {&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  31:  &lt;/span&gt;        &lt;span class="rem"&gt;// there seems to be a bug with RenderPartial tainting the page's view data&lt;/span&gt;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  32:  &lt;/span&gt;        &lt;span class="rem"&gt;// so we should capture the current view path, and revert back after rendering&lt;/span&gt;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  33:  &lt;/span&gt;        &lt;span class="kwrd"&gt;string&lt;/span&gt; originalViewPath = (&lt;span class="kwrd"&gt;string&lt;/span&gt;) viewContext.ViewData[ViewPathKey];&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  34:  &lt;/span&gt;        &lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  35:  &lt;/span&gt;        viewContext.ViewData[ViewPathKey] = ViewPath;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  36:  &lt;/span&gt;        &lt;span class="kwrd"&gt;base&lt;/span&gt;.Render(viewContext, writer);&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  37:  &lt;/span&gt;        &lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  38:  &lt;/span&gt;        viewContext.ViewData[ViewPathKey] = originalViewPath;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  39:  &lt;/span&gt;    }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  40:  &lt;/span&gt;}&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;As you can see, it's much simpler now. Also, it seems as if there's a bug with the current Beta bits when you have a RenderPartial on your page, there's no isolation and the view's path is not correct later. Simple fix by simply grabbing the original view path, setting it to the new path, rendering, and then reverting back.&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;h4&gt;Getting back to Extension Methods&lt;/h4&gt;

&lt;p&gt;And now that we have our path again in our ViewData, we can revert back to using extension methods to extract the path when doing both Global and Local resources. As you can see below, should you be using any other ViewEngine it will always work for Global resources.&lt;/p&gt;

&lt;div class="csharpcode"&gt;
  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   1:  &lt;/span&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; ResourceExtensions&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   2:  &lt;/span&gt;{&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   3:  &lt;/span&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; Resource(&lt;span class="kwrd"&gt;this&lt;/span&gt; Controller controller, &lt;span class="kwrd"&gt;string&lt;/span&gt; expression, &lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   4:  &lt;/span&gt;                                                  &lt;span class="kwrd"&gt;params&lt;/span&gt; &lt;span class="kwrd"&gt;object&lt;/span&gt;[] args)&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   5:  &lt;/span&gt;    {&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   6:  &lt;/span&gt;        ResourceExpressionFields fields = GetResourceFields(expression, &lt;span class="str"&gt;&amp;quot;~/&amp;quot;&lt;/span&gt;);&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   7:  &lt;/span&gt;        &lt;span class="kwrd"&gt;return&lt;/span&gt; GetGlobalResource(fields, args);&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   8:  &lt;/span&gt;    }&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   9:  &lt;/span&gt;&amp;#160;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  10:  &lt;/span&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; Resource(&lt;span class="kwrd"&gt;this&lt;/span&gt; HtmlHelper htmlHelper, &lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  11:  &lt;/span&gt;                                                  &lt;span class="kwrd"&gt;string&lt;/span&gt; expression, &lt;span class="kwrd"&gt;params&lt;/span&gt; &lt;span class="kwrd"&gt;object&lt;/span&gt;[] args)&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  12:  &lt;/span&gt;    {&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  13:  &lt;/span&gt;        &lt;span class="kwrd"&gt;string&lt;/span&gt; path = (&lt;span class="kwrd"&gt;string&lt;/span&gt;)htmlHelper.ViewData[LocalizationWebFormView.ViewPathKey];&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  14:  &lt;/span&gt;        &lt;span class="kwrd"&gt;if&lt;/span&gt; (&lt;span class="kwrd"&gt;string&lt;/span&gt;.IsNullOrEmpty(path))&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  15:  &lt;/span&gt;            path = &lt;span class="str"&gt;&amp;quot;~/&amp;quot;&lt;/span&gt;;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  16:  &lt;/span&gt;&amp;#160;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  17:  &lt;/span&gt;        ResourceExpressionFields fields = GetResourceFields(expression, path);&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  18:  &lt;/span&gt;        &lt;span class="kwrd"&gt;if&lt;/span&gt; (!&lt;span class="kwrd"&gt;string&lt;/span&gt;.IsNullOrEmpty(fields.ClassKey))&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  19:  &lt;/span&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; GetGlobalResource(fields, args);&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  20:  &lt;/span&gt;&amp;#160;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  21:  &lt;/span&gt;        &lt;span class="kwrd"&gt;return&lt;/span&gt; GetLocalResource(path, fields, args);&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  22:  &lt;/span&gt;    }&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  23:  &lt;/span&gt;&amp;#160;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  24:  &lt;/span&gt;    &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; GetLocalResource(&lt;span class="kwrd"&gt;string&lt;/span&gt; path, ResourceExpressionFields fields, &lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  25:  &lt;/span&gt;                                                     &lt;span class="kwrd"&gt;object&lt;/span&gt;[] args)&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  26:  &lt;/span&gt;    {&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  27:  &lt;/span&gt;        &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt;.Format((&lt;span class="kwrd"&gt;string&lt;/span&gt;)HttpContext.GetLocalResourceObject(path, &lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  28:  &lt;/span&gt;                               fields.ResourceKey, CultureInfo.CurrentUICulture), args);&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  29:  &lt;/span&gt;    }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  30:  &lt;/span&gt;&amp;#160;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  31:  &lt;/span&gt;    &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; GetGlobalResource(ResourceExpressionFields fields, &lt;span class="kwrd"&gt;object&lt;/span&gt;[] args)&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  32:  &lt;/span&gt;    {&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  33:  &lt;/span&gt;        &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt;.Format((&lt;span class="kwrd"&gt;string&lt;/span&gt;)HttpContext.GetGlobalResourceObject(&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  34:  &lt;/span&gt;             fields.ClassKey, fields.ResourceKey, CultureInfo.CurrentUICulture), args);&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  35:  &lt;/span&gt;    }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  36:  &lt;/span&gt;&amp;#160;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  37:  &lt;/span&gt;    &lt;span class="kwrd"&gt;static&lt;/span&gt; ResourceExpressionFields GetResourceFields(&lt;span class="kwrd"&gt;string&lt;/span&gt; expression, &lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  38:  &lt;/span&gt;                                                              &lt;span class="kwrd"&gt;string&lt;/span&gt; virtualPath)&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  39:  &lt;/span&gt;    {&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  40:  &lt;/span&gt;        var context = &lt;span class="kwrd"&gt;new&lt;/span&gt; ExpressionBuilderContext(virtualPath);&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  41:  &lt;/span&gt;        var builder = &lt;span class="kwrd"&gt;new&lt;/span&gt; ResourceExpressionBuilder();&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  42:  &lt;/span&gt;        &lt;span class="kwrd"&gt;return&lt;/span&gt; (ResourceExpressionFields)builder.ParseExpression(&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  43:  &lt;/span&gt;                                          expression, &lt;span class="kwrd"&gt;typeof&lt;/span&gt;(&lt;span class="kwrd"&gt;string&lt;/span&gt;), context);&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  44:  &lt;/span&gt;    }&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  45:  &lt;/span&gt;}&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Again, thanks to Brad, this implementation seems "less dirty". You can &lt;a href="http://www.eworldui.net/files/mvcdemos/LocalizationViaExtensions.zip"&gt;download the source for this here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;
&lt;a href="http://www.dotnetkicks.com/kick/?url=http%3a%2f%2fblog.eworldui.net%2fpost.aspx%3fid%3d5a8fe5de-931f-4709-8ec1-ba00c72c6782"&gt;&lt;img alt="kick it on DotNetKicks.com" src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fblog.eworldui.net%2fpost.aspx%3fid%3d5a8fe5de-931f-4709-8ec1-ba00c72c6782" border="0" /&gt;&lt;/a&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/eworldui?a=HZlS-s7Wjvk:MzIe3N7MVsQ:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/eworldui?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/eworldui?a=HZlS-s7Wjvk:MzIe3N7MVsQ:D7DqB2pKExk"&gt;&lt;img src="http://feeds.feedburner.com/~ff/eworldui?i=HZlS-s7Wjvk:MzIe3N7MVsQ:D7DqB2pKExk" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/eworldui/~4/HZlS-s7Wjvk" height="1" width="1"/&gt;</description>
      <link>http://feedproxy.google.com/~r/eworldui/~3/HZlS-s7Wjvk/post.aspx</link>
      <author>matthaw</author>
      <comments>http://blog.eworldui.net/post/2008/10/ASPNET-MVC-Simplified-Localization-via-ViewEngines.aspx#comment</comments>
      <guid isPermaLink="false">http://blog.eworldui.net/post.aspx?id=5a8fe5de-931f-4709-8ec1-ba00c72c6782</guid>
      <pubDate>Wed, 22 Oct 2008 16:56:39 -0800</pubDate>
      <category>.NET</category>
      <category>ASP.NET</category>
      <category>MVC</category>
      <category>Programming</category>
      <dc:publisher>matthaw</dc:publisher>
      <pingback:server>http://blog.eworldui.net/pingback.axd</pingback:server>
      <pingback:target>http://blog.eworldui.net/post.aspx?id=5a8fe5de-931f-4709-8ec1-ba00c72c6782</pingback:target>
      <slash:comments>91</slash:comments>
      <trackback:ping>http://blog.eworldui.net/trackback.axd?id=5a8fe5de-931f-4709-8ec1-ba00c72c6782</trackback:ping>
      <wfw:comment>http://blog.eworldui.net/post/2008/10/ASPNET-MVC-Simplified-Localization-via-ViewEngines.aspx#comment</wfw:comment>
      <wfw:commentRss>http://blog.eworldui.net/syndication.axd?post=5a8fe5de-931f-4709-8ec1-ba00c72c6782</wfw:commentRss>
    <feedburner:origLink>http://blog.eworldui.net/post.aspx?id=5a8fe5de-931f-4709-8ec1-ba00c72c6782</feedburner:origLink></item>
    <item>
      <title>ASP.NET MVC: Localization Delegated via View Engines</title>
      <description>&lt;p&gt;&lt;strong&gt;&lt;font color="#ff0000"&gt;Update&lt;/font&gt;&lt;/strong&gt;: Please &lt;a href="http://blog.eworldui.net/post/2008/10/ASPNET-MVC-Simplified-Localization-via-ViewEngines.aspx"&gt;see this newer post&lt;/a&gt;. It simplifies this solution drastically, and I don't recommend this version anymore!&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;I've &lt;a href="http://blog.eworldui.net/post/2008/05/ASPNET-MVC---Localization.aspx"&gt;previously blogged about how to add localization support&lt;/a&gt; within ASP.NET MVC before, but that codebase was based on Preview 3, and now that the beta is out there, the code just doesn't work anymore. Period. The concepts I had originally had put out there really don't fly well in the Beta world, or, within the "real" world in which people are using more than just the WebFormViewEngine for their rendering. So, why is there this big disconnect now? Well. it's not so much that global resources fail to work, it's more local resources don't really apply "generally" anymore. &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;While looking into a solution, and bouncing ideas off of &lt;a href="http://www.haacked.com/"&gt;Phil&lt;/a&gt; &amp;amp; &lt;a href="http://bradwilson.typepad.com/"&gt;Brad&lt;/a&gt;, I came to the realization that, just like in the Matrix, &lt;em&gt;"There is no spoon"&lt;/em&gt; or rather, replace "spoon" with "view location" and you have your reasoning. Now, before you start ranting, let me explain. Yes, there are physical locations at which your views are located, but what if you're ViewEngine was pulling the view's from a database? No guarantee that a "general" solution could achieve local resource support based on a HtmlHelper extensino. However, if you left the local resource delegation up to a ViewEngine, you can now have a concept of a location in relevance to it. (And yes, the point may be moot if you use a different Resource Provider than the asp.net built-in one)&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;So where does that leave us? Well, we need a general way to access both global and local resources within a View, and global resources within a Controller. Ultimately, the code used to get the resources hasn't changed from my original implementation, however, because we no longer have that concept of a view location, the new implementation delegates this decision correctly to the view engine. Also, before I show the proof of concept, I want to warn you that the guts for my view rendering logic is nearly a copy from what is in the WebFormView source.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;So here's the overall design is as follows:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Any view engine / views can out-of-the-box use "global resources" &lt;/li&gt;    &lt;li&gt;A view engine can decide if it's views can participate in "local resources" by supplying it's own implementation. &lt;/li&gt;    &lt;li&gt;A controller can request "global resources" for messages it's setting within ViewData. &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;Now, because I wanted to provide a default implementation for the WebFormViewEngine, the implementation isn't nearly as clean as one would like, but it does work great, and falls back to using non-derived ViewPage's and ViewUserControl's when necessary.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h4&gt;View Implementation&lt;/h4&gt;  &lt;p&gt;We start by deriving ViewPage and ViewUserControl to support localization. These new implementations will add a ResourceHelper, just like Ajax / Html / Url, so that within your view, you can directly access a resource.&lt;/p&gt;  &lt;div class="csharpcode"&gt;   &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   1:  &lt;/span&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; LocalizedViewPage : ViewPage, ILocalizedView&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   2:  &lt;/span&gt;{&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   3:  &lt;/span&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; ResourceHelper Resource { get; set; }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   4:  &lt;/span&gt;}&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   5:  &lt;/span&gt;&amp;#160;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   6:  &lt;/span&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; LocalizedViewPage&amp;lt;TModel&amp;gt; : ViewPage&amp;lt;TModel&amp;gt;, ILocalizedView&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   7:  &lt;/span&gt;    &lt;span class="kwrd"&gt;where&lt;/span&gt; TModel : &lt;span class="kwrd"&gt;class&lt;/span&gt;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   8:  &lt;/span&gt;{&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   9:  &lt;/span&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; ResourceHelper Resource { get; set; }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  10:  &lt;/span&gt;}&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  11:  &lt;/span&gt;&amp;#160;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  12:  &lt;/span&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; LocalizedViewUserControl : ViewUserControl, ILocalizedView&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  13:  &lt;/span&gt;{&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  14:  &lt;/span&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; ResourceHelper Resource { get; set; }&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  15:  &lt;/span&gt;}&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  16:  &lt;/span&gt;&amp;#160;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  17:  &lt;/span&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; LocalizedViewUserControl&amp;lt;TModel&amp;gt; : ViewUserControl&amp;lt;TModel&amp;gt;, ILocalizedView&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  18:  &lt;/span&gt;    &lt;span class="kwrd"&gt;where&lt;/span&gt; TModel : &lt;span class="kwrd"&gt;class&lt;/span&gt;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  19:  &lt;/span&gt;{&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  20:  &lt;/span&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; ResourceHelper Resource { get; set; }&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  21:  &lt;/span&gt;}&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;The interface ILocalizedView is simply an abstraction I put out so I could determine what type of View I was working with in the View Engine.&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;h4&gt;Resource Helper Implementation&lt;/h4&gt;

&lt;p&gt;The resource helper implementation is very straight forward. As previously stated, ResourceHelper is the base that adds support for global resources. The WebFormResourceHelper is what the new web form view engine implementation uses to add support for both global and local resources. As you'll see, WebFormResourceHelper is initialized with the virtual path of the currently rendering view so that it can correctly find the local resource.&lt;/p&gt;

&lt;div class="csharpcode"&gt;
  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   1:  &lt;/span&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; ResourceExtensions&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   2:  &lt;/span&gt;{&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   3:  &lt;/span&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; Resource(&lt;span class="kwrd"&gt;this&lt;/span&gt; Controller controller, &lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   4:  &lt;/span&gt;                                       &lt;span class="kwrd"&gt;string&lt;/span&gt; expression, &lt;span class="kwrd"&gt;params&lt;/span&gt; &lt;span class="kwrd"&gt;object&lt;/span&gt;[] args)&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   5:  &lt;/span&gt;    {&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   6:  &lt;/span&gt;        ResourceExpressionFields fields = GetResourceFields(expression, &lt;span class="str"&gt;&amp;quot;~/&amp;quot;&lt;/span&gt;);&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   7:  &lt;/span&gt;        &lt;span class="kwrd"&gt;return&lt;/span&gt; GetGlobalResource(fields, args);&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   8:  &lt;/span&gt;    }&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   9:  &lt;/span&gt;&amp;#160;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  10:  &lt;/span&gt;    &lt;span class="kwrd"&gt;internal&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; GetGlobalResource(ResourceExpressionFields fields, &lt;span class="kwrd"&gt;object&lt;/span&gt;[] args)&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  11:  &lt;/span&gt;    {&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  12:  &lt;/span&gt;        &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt;.Format((&lt;span class="kwrd"&gt;string&lt;/span&gt;)HttpContext.GetGlobalResourceObject(&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  13:  &lt;/span&gt;                                                    fields.ClassKey, fields.ResourceKey, &lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  14:  &lt;/span&gt;                                                    CultureInfo.CurrentUICulture), args);&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  15:  &lt;/span&gt;    }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  16:  &lt;/span&gt;&amp;#160;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  17:  &lt;/span&gt;&amp;#160;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  18:  &lt;/span&gt;    &lt;span class="kwrd"&gt;internal&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; ResourceExpressionFields GetResourceFields(&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  19:  &lt;/span&gt;                                  &lt;span class="kwrd"&gt;string&lt;/span&gt; expression, &lt;span class="kwrd"&gt;string&lt;/span&gt; virtualPath)&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  20:  &lt;/span&gt;    {&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  21:  &lt;/span&gt;        var context = &lt;span class="kwrd"&gt;new&lt;/span&gt; ExpressionBuilderContext(virtualPath);&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  22:  &lt;/span&gt;        var builder = &lt;span class="kwrd"&gt;new&lt;/span&gt; ResourceExpressionBuilder();&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  23:  &lt;/span&gt;        &lt;span class="kwrd"&gt;return&lt;/span&gt; (ResourceExpressionFields)builder.ParseExpression(&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  24:  &lt;/span&gt;                                  expression, &lt;span class="kwrd"&gt;typeof&lt;/span&gt;(&lt;span class="kwrd"&gt;string&lt;/span&gt;), context);&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  25:  &lt;/span&gt;    }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  26:  &lt;/span&gt;}&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  27:  &lt;/span&gt;&amp;#160;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  28:  &lt;/span&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; ResourceHelper&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  29:  &lt;/span&gt;{&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  30:  &lt;/span&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;virtual&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; GetString(&lt;span class="kwrd"&gt;string&lt;/span&gt; expression, &lt;span class="kwrd"&gt;params&lt;/span&gt; &lt;span class="kwrd"&gt;object&lt;/span&gt;[] args)&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  31:  &lt;/span&gt;    {&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  32:  &lt;/span&gt;        ResourceExpressionFields fields = GetResourceFields(expression, &lt;span class="str"&gt;&amp;quot;~/&amp;quot;&lt;/span&gt;);&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  33:  &lt;/span&gt;        &lt;span class="kwrd"&gt;if&lt;/span&gt; (&lt;span class="kwrd"&gt;string&lt;/span&gt;.IsNullOrEmpty(fields.ClassKey))&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  34:  &lt;/span&gt;            &lt;span class="kwrd"&gt;throw&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; InvalidOperationException(&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  35:  &lt;/span&gt;                     &lt;span class="str"&gt;&amp;quot;The resource helper does not support local resources.&amp;quot;&lt;/span&gt;);&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  36:  &lt;/span&gt;&amp;#160;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  37:  &lt;/span&gt;        &lt;span class="kwrd"&gt;return&lt;/span&gt; GetGlobalResource(fields, args);&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  38:  &lt;/span&gt;    }&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  39:  &lt;/span&gt;&amp;#160;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  40:  &lt;/span&gt;    &lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; GetGlobalResource(ResourceExpressionFields fields, &lt;span class="kwrd"&gt;object&lt;/span&gt;[] args)&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  41:  &lt;/span&gt;    {&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  42:  &lt;/span&gt;        &lt;span class="kwrd"&gt;return&lt;/span&gt; ResourceExtensions.GetGlobalResource(fields, args);&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  43:  &lt;/span&gt;    }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  44:  &lt;/span&gt;&amp;#160;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  45:  &lt;/span&gt;    &lt;span class="kwrd"&gt;protected&lt;/span&gt; ResourceExpressionFields GetResourceFields(&lt;span class="kwrd"&gt;string&lt;/span&gt; expression, &lt;span class="kwrd"&gt;string&lt;/span&gt; virtualPath)&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  46:  &lt;/span&gt;    {&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  47:  &lt;/span&gt;        &lt;span class="kwrd"&gt;return&lt;/span&gt; ResourceExtensions.GetResourceFields(expression, virtualPath);&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  48:  &lt;/span&gt;    }&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  49:  &lt;/span&gt;}&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  50:  &lt;/span&gt;&amp;#160;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  51:  &lt;/span&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; WebFormResourceHelper : ResourceHelper&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  52:  &lt;/span&gt;{&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  53:  &lt;/span&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; WebFormResourceHelper(&lt;span class="kwrd"&gt;string&lt;/span&gt; virtualPath)&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  54:  &lt;/span&gt;    {&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  55:  &lt;/span&gt;        VirtualPath = virtualPath;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  56:  &lt;/span&gt;    }&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  57:  &lt;/span&gt;&amp;#160;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  58:  &lt;/span&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; VirtualPath { get; &lt;span class="kwrd"&gt;private&lt;/span&gt; set; }&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  59:  &lt;/span&gt;&amp;#160;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  60:  &lt;/span&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; GetString(&lt;span class="kwrd"&gt;string&lt;/span&gt; expression, &lt;span class="kwrd"&gt;params&lt;/span&gt; &lt;span class="kwrd"&gt;object&lt;/span&gt;[] args)&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  61:  &lt;/span&gt;    {&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  62:  &lt;/span&gt;        ResourceExpressionFields fields = GetResourceFields(expression, VirtualPath);&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  63:  &lt;/span&gt;        &lt;span class="kwrd"&gt;if&lt;/span&gt; (!&lt;span class="kwrd"&gt;string&lt;/span&gt;.IsNullOrEmpty(fields.ClassKey))&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  64:  &lt;/span&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; GetGlobalResource(fields, args);&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  65:  &lt;/span&gt;&amp;#160;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  66:  &lt;/span&gt;        &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt;.Format((&lt;span class="kwrd"&gt;string&lt;/span&gt;) HttpContext.GetLocalResourceObject(&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  67:  &lt;/span&gt;                                                           VirtualPath, fields.ResourceKey, &lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  68:  &lt;/span&gt;                                                           CultureInfo.CurrentUICulture), args);&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  69:  &lt;/span&gt;    }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  70:  &lt;/span&gt;}&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;You'll also notice that I've included a controller extension method for extracting global resources. This hasn't changed from the original implementation, but it's straight forward to use.&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;h4&gt;View Engine Implementation&lt;/h4&gt;

&lt;p&gt;This is where the rubber meets the road. Since we're now delegating that a ViewEngine can choose to support local resources, the derived view engine implementation is where it supplies it's own ResourceHelper, if it so chooses. In my example, I derive from the WebFormViewEngine and WebFormView, and provide this implementation to supply the WebFormResourceHelper to my localized views. For brevity, and the fact that I didn't write the code for rendering, I'll leave it up to you to see the full implementation for the LocalizedWebFormView in the download. However, the critical portion that you'll see is the following:&lt;/p&gt;

&lt;div class="csharpcode"&gt;
  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   1:  &lt;/span&gt;var localizedPage = page &lt;span class="kwrd"&gt;as&lt;/span&gt; ILocalizedView;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   2:  &lt;/span&gt;&lt;span class="kwrd"&gt;if&lt;/span&gt; (localizedPage != &lt;span class="kwrd"&gt;null&lt;/span&gt;)&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   3:  &lt;/span&gt;    localizedPage.Resource = &lt;span class="kwrd"&gt;new&lt;/span&gt; WebFormResourceHelper(ViewPath);&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   4:  &lt;/span&gt;page.RenderView(context);&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;And that's it. In your view, you can now derive from LocalizedViewPage and get access to your global and local resources by doing&lt;/p&gt;

&lt;div class="csharpcode"&gt;
  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   1:  &lt;/span&gt;// global resource&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   2:  &lt;/span&gt;&lt;span class="asp"&gt;&amp;lt;%&lt;/span&gt;= Resource.GetString(&lt;span class="str"&gt;&amp;quot;MvcExample, Welcome&amp;quot;&lt;/span&gt;) &lt;span class="asp"&gt;%&amp;gt;&lt;/span&gt;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   3:  &lt;/span&gt;&amp;#160;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   4:  &lt;/span&gt;// local resource&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   5:  &lt;/span&gt;&lt;span class="asp"&gt;&amp;lt;%&lt;/span&gt;= Resource.GetString(&lt;span class="str"&gt;&amp;quot;Welcome&amp;quot;&lt;/span&gt;) &lt;span class="asp"&gt;%&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;h4&gt;How does this fit with other View Engines?&lt;/h4&gt;

&lt;p&gt;View engines need to simply add a reference to the ResourceHelper so that their view's can gain access to it. Obviously, they'll also need to change their ViewEngine to set an appropriate ResourceHelper when instantiating the view, but those view engines can explicitly determine how they would like to treat resources (even completely ignoring Global &amp;amp; Local resources). &lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;And that's it, our View Engine now is completely in control of where my resources come from. They can use the baked-in ASP.NET resource provider, their own logic, or whatever! Again, this implementation is no where near baked, and I strongly urge you to look at your solution to see how this would fit in, and (obviously) make the code "production worthy". I'm hoping that some of these concepts make it into future MVC releases. You can also &lt;a href="http://www.eworldui.net/files/mvcdemos/LocalizationViaViewEngines.zip"&gt;download the source&lt;/a&gt; for these files here. Enjoy!&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;
&lt;a href="http://www.dotnetkicks.com/kick/?url=http%3a%2f%2fblog.eworldui.net%2fpost%2f2008%2f10%2fASPNET-MVC-Localization-via-View-Engines.aspx"&gt;&lt;img alt="kick it on DotNetKicks.com" src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fblog.eworldui.net%2fpost%2f2008%2f10%2fASPNET-MVC-Localization-via-View-Engines.aspx" border="0" /&gt;&lt;/a&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/eworldui?a=iW3r8CohRos:lqJxwQflIQQ:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/eworldui?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/eworldui?a=iW3r8CohRos:lqJxwQflIQQ:D7DqB2pKExk"&gt;&lt;img src="http://feeds.feedburner.com/~ff/eworldui?i=iW3r8CohRos:lqJxwQflIQQ:D7DqB2pKExk" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/eworldui/~4/iW3r8CohRos" height="1" width="1"/&gt;</description>
      <link>http://feedproxy.google.com/~r/eworldui/~3/iW3r8CohRos/post.aspx</link>
      <author>matthaw</author>
      <comments>http://blog.eworldui.net/post/2008/10/ASPNET-MVC-Localization-via-View-Engines.aspx#comment</comments>
      <guid isPermaLink="false">http://blog.eworldui.net/post.aspx?id=d2ed3285-293a-45ad-a529-9c8df198c1e0</guid>
      <pubDate>Wed, 22 Oct 2008 14:02:59 -0800</pubDate>
      <category>.NET</category>
      <category>ASP.NET</category>
      <category>MVC</category>
      <category>Programming</category>
      <dc:publisher>matthaw</dc:publisher>
      <pingback:server>http://blog.eworldui.net/pingback.axd</pingback:server>
      <pingback:target>http://blog.eworldui.net/post.aspx?id=d2ed3285-293a-45ad-a529-9c8df198c1e0</pingback:target>
      <slash:comments>28</slash:comments>
      <trackback:ping>http://blog.eworldui.net/trackback.axd?id=d2ed3285-293a-45ad-a529-9c8df198c1e0</trackback:ping>
      <wfw:comment>http://blog.eworldui.net/post/2008/10/ASPNET-MVC-Localization-via-View-Engines.aspx#comment</wfw:comment>
      <wfw:commentRss>http://blog.eworldui.net/syndication.axd?post=d2ed3285-293a-45ad-a529-9c8df198c1e0</wfw:commentRss>
    <feedburner:origLink>http://blog.eworldui.net/post.aspx?id=d2ed3285-293a-45ad-a529-9c8df198c1e0</feedburner:origLink></item>
    <item>
      <title>ASP.NET MVC Preview 4 New Finds</title>
      <description>&lt;p&gt;So I've been checking over the source code for the latest ASP.NET MVC P4 release out on CodePlex, and have found some very interesting things.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;font color="#ff8000" size="4"&gt;1.&lt;/font&gt; There's a variant codebase that is very similar to my &lt;a href="http://blog.eworldui.net/post/2008/05/Lambda-Based-RedirectToAction-Sample-Updated-to-MVC-Preview-3.aspx" target="_blank"&gt;RedirectToAction via Lambda expressions&lt;/a&gt; contained within the Futures/MvcFutures/Internal directory, "ExpressionHelper.cs". With this futures drop, the call will return a RouteValueDictionary, in which you turn around and call RedirectToRoute. In my version, of RedirectToAction, this is all taken care of for you, as well as it supports not having to explicitly give the type of your controller. Either way, here's the example on how to use this if you prefer:&lt;/p&gt;  &lt;div class="csharpcode"&gt;   &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   1:  &lt;/span&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; Microsoft.Web.Mvc.Internal;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   2:  &lt;/span&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Web.Routing;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   3:  &lt;/span&gt;&amp;#160;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   4:  &lt;/span&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; HomeController : Controller&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   5:  &lt;/span&gt;{&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   6:  &lt;/span&gt;   &lt;span class="kwrd"&gt;public&lt;/span&gt; ActionResult Index()&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   7:  &lt;/span&gt;   {&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   8:  &lt;/span&gt;      &lt;span class="kwrd"&gt;return&lt;/span&gt; View();&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   9:  &lt;/span&gt;   }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  10:  &lt;/span&gt;&amp;#160;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  11:  &lt;/span&gt;   &lt;span class="kwrd"&gt;public&lt;/span&gt; ActionResult DoRedirect()&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  12:  &lt;/span&gt;   {&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  13:  &lt;/span&gt;      RouteValueDictionary values = &lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  14:  &lt;/span&gt;         ExpressionHelper.GetRouteValuesFromExpression&amp;lt;HomeController&amp;gt;(c =&amp;gt; c.Index());&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  15:  &lt;/span&gt;      &lt;span class="kwrd"&gt;return&lt;/span&gt; RedirectToRoute(values);&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  16:  &lt;/span&gt;   }&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  17:  &lt;/span&gt;}&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;&lt;font color="#ff8000" size="4"&gt;2.&lt;/font&gt; The &lt;a href="http://blog.eworldui.net/post/2008/06/RedirectToAction-Nasty-Bug-in-ASPNET-MVC-Preview-3.aspx" target="_blank"&gt;RedirectToAction bug&lt;/a&gt; I blogged about has been fixed. &lt;/p&gt;

&lt;p&gt;&lt;font color="#ff8000" size="4"&gt;3.&lt;/font&gt; They've introduced a helper extension method (MvcControlDataBinder.SourceToDictionary) to convert data sources to a dictionary of values. The supported data source types include &lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;DataSet &lt;/li&gt;

  &lt;li&gt;DataTable &lt;/li&gt;

  &lt;li&gt;IDataReader &lt;/li&gt;

  &lt;li&gt;IList &lt;/li&gt;

  &lt;li&gt;Array &lt;/li&gt;

  &lt;li&gt;IQueryable &lt;/li&gt;

  &lt;li&gt;IEnumerable &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Below is an example on how to use this method. While I would never use this to convert a List of models normally, I could see where if you simply need to get truncated key/value list of data with various other sources like IDataReader or IQueryable, this would be beneficial.&lt;/p&gt;

&lt;div class="csharpcode"&gt;
  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   1:  &lt;/span&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; ActionResult Products()&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   2:  &lt;/span&gt;{&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   3:  &lt;/span&gt;    List&amp;lt;Product&amp;gt; products = &lt;span class="kwrd"&gt;new&lt;/span&gt; List&amp;lt;Product&amp;gt;()&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   4:  &lt;/span&gt;    {&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   5:  &lt;/span&gt;        &lt;span class="kwrd"&gt;new&lt;/span&gt; Product(1, &lt;span class="str"&gt;&amp;quot;16 Speed&amp;quot;&lt;/span&gt;, 499.99m),&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   6:  &lt;/span&gt;        &lt;span class="kwrd"&gt;new&lt;/span&gt; Product(2, &lt;span class="str"&gt;&amp;quot;24 Speed&amp;quot;&lt;/span&gt;, 699.99m)&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   7:  &lt;/span&gt;    };&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   8:  &lt;/span&gt;&amp;#160;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   9:  &lt;/span&gt;    Dictionary&amp;lt;&lt;span class="kwrd"&gt;object&lt;/span&gt;, &lt;span class="kwrd"&gt;object&lt;/span&gt;&amp;gt; data = &lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  10:  &lt;/span&gt;        MvcControlDataBinder.SourceToDictionary(products, &lt;span class="str"&gt;&amp;quot;Id&amp;quot;&lt;/span&gt;, &lt;span class="str"&gt;&amp;quot;Name&amp;quot;&lt;/span&gt;);&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  11:  &lt;/span&gt;    ViewData[&lt;span class="str"&gt;&amp;quot;Data&amp;quot;&lt;/span&gt;] = data;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  12:  &lt;/span&gt;&amp;#160;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  13:  &lt;/span&gt;    &lt;span class="kwrd"&gt;return&lt;/span&gt; View();&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  14:  &lt;/span&gt;}&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;&lt;font color="#ff8000" size="4"&gt;4.&lt;/font&gt; The new Ajax support. I'm not going to detail this as &lt;a href="http://www.hanselman.com/blog/ASPNETMVCPreview4UsingAjaxAndAjaxForm.aspx" target="_blank"&gt;Scott Hanselman's post&lt;/a&gt; covered a good example and ScottGu will eventually give Part 2 which will be very detailed.&lt;/p&gt;

&lt;p&gt;&lt;font color="#ff8000" size="4"&gt;5.&lt;/font&gt; As &lt;a href="http://weblogs.asp.net/scottgu/archive/2008/07/14/asp-net-mvc-preview-4-release-part-1.aspx" target="_blank"&gt;ScottGu already indicated&lt;/a&gt;, the Mvc Framework comes with a bunch of new Action Filters, including&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;AuthorizeAttribute - which uses the membership framework for user authentication and user &amp;amp; role based security. &lt;/li&gt;

  &lt;li&gt;HandleErrorAttribute - which will enable you to handle exceptions that occur by rendering a specific view when an error occurs. This is equitable to the catch-all error page. &lt;/li&gt;

  &lt;li&gt;OutputCacheAttribute - Yes, this is what it says it is. Think ASP.NET output caching, and thats what this is. &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;font color="#ff8000" size="4"&gt;6.&lt;/font&gt; TempData is now "testing friendly"! Well, right out of the box now, that is. They've introduced a new interface ITempDataProvider (and subsequent SessionStateTempDataProvider) that will only be used only when Execute is called from the Controller. The reason TempData is now tester friendly, is that by default it uses TempDataDictionary as a backing field, and Execute will Load/Save from the TempDataProvider set to/from TempData.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.dotnetkicks.com/kick/?url=http%3a%2f%2fblog.eworldui.net%2fpost%2f2008%2f07%2fASPNET-MVC-Preview-4-New-Finds.aspx"&gt;&lt;img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fblog.eworldui.net%2fpost%2f2008%2f07%2fASPNET-MVC-Preview-4-New-Finds.aspx" border="0" alt="kick it on DotNetKicks.com" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/eworldui?a=HwLp92uqAl4:2Niz1Gs_I3g:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/eworldui?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/eworldui?a=HwLp92uqAl4:2Niz1Gs_I3g:D7DqB2pKExk"&gt;&lt;img src="http://feeds.feedburner.com/~ff/eworldui?i=HwLp92uqAl4:2Niz1Gs_I3g:D7DqB2pKExk" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/eworldui/~4/HwLp92uqAl4" height="1" width="1"/&gt;</description>
      <link>http://feedproxy.google.com/~r/eworldui/~3/HwLp92uqAl4/post.aspx</link>
      <author>matthaw</author>
      <comments>http://blog.eworldui.net/post/2008/07/ASPNET-MVC-Preview-4-New-Finds.aspx#comment</comments>
      <guid isPermaLink="false">http://blog.eworldui.net/post.aspx?id=57121f68-ba29-4ab3-abca-cf2c2dbb1775</guid>
      <pubDate>Thu, 17 Jul 2008 00:49:53 -0800</pubDate>
      <category>.NET</category>
      <category>ASP.NET</category>
      <category>MVC</category>
      <category>Programming</category>
      <dc:publisher>matthaw</dc:publisher>
      <pingback:server>http://blog.eworldui.net/pingback.axd</pingback:server>
      <pingback:target>http://blog.eworldui.net/post.aspx?id=57121f68-ba29-4ab3-abca-cf2c2dbb1775</pingback:target>
      <slash:comments>113</slash:comments>
      <trackback:ping>http://blog.eworldui.net/trackback.axd?id=57121f68-ba29-4ab3-abca-cf2c2dbb1775</trackback:ping>
      <wfw:comment>http://blog.eworldui.net/post/2008/07/ASPNET-MVC-Preview-4-New-Finds.aspx#comment</wfw:comment>
      <wfw:commentRss>http://blog.eworldui.net/syndication.axd?post=57121f68-ba29-4ab3-abca-cf2c2dbb1775</wfw:commentRss>
    <feedburner:origLink>http://blog.eworldui.net/post.aspx?id=57121f68-ba29-4ab3-abca-cf2c2dbb1775</feedburner:origLink></item>
    <item>
      <title>Routing + WebForms + Auto &amp;ldquo;Binding&amp;rdquo; Properties</title>
      <description>&lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;Just ran across this &lt;a href="http://blog.jeremyskinner.me.uk/2008/06/21/aspnet-routing-databinding-and-webforms/" target="_blank"&gt;excellent post&lt;/a&gt; by Jeremy Skinner. Just shows on how much power &amp;amp; flexibility the new routing framework gives you. This really is making me want to really focus on my slack project of using Routing instead of Url Rewriting at work.&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/eworldui?a=CatBQb4amAE:NKwdqj7NWvo:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/eworldui?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/eworldui?a=CatBQb4amAE:NKwdqj7NWvo:D7DqB2pKExk"&gt;&lt;img src="http://feeds.feedburner.com/~ff/eworldui?i=CatBQb4amAE:NKwdqj7NWvo:D7DqB2pKExk" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/eworldui/~4/CatBQb4amAE" height="1" width="1"/&gt;</description>
      <link>http://feedproxy.google.com/~r/eworldui/~3/CatBQb4amAE/post.aspx</link>
      <author>matthaw</author>
      <comments>http://blog.eworldui.net/post/2008/06/Routing-2b-WebForms-2b-Auto-ldquo3bBindingrdquo3b-Properties.aspx#comment</comments>
      <guid isPermaLink="false">http://blog.eworldui.net/post.aspx?id=18f7fad9-efb9-4bc5-9ec8-253c566d0a2a</guid>
      <pubDate>Sat, 21 Jun 2008 10:51:08 -0800</pubDate>
      <dc:publisher>matthaw</dc:publisher>
      <pingback:server>http://blog.eworldui.net/pingback.axd</pingback:server>
      <pingback:target>http://blog.eworldui.net/post.aspx?id=18f7fad9-efb9-4bc5-9ec8-253c566d0a2a</pingback:target>
      <slash:comments>3</slash:comments>
      <trackback:ping>http://blog.eworldui.net/trackback.axd?id=18f7fad9-efb9-4bc5-9ec8-253c566d0a2a</trackback:ping>
      <wfw:comment>http://blog.eworldui.net/post/2008/06/Routing-2b-WebForms-2b-Auto-ldquo3bBindingrdquo3b-Properties.aspx#comment</wfw:comment>
      <wfw:commentRss>http://blog.eworldui.net/syndication.axd?post=18f7fad9-efb9-4bc5-9ec8-253c566d0a2a</wfw:commentRss>
    <feedburner:origLink>http://blog.eworldui.net/post.aspx?id=18f7fad9-efb9-4bc5-9ec8-253c566d0a2a</feedburner:origLink></item>
    <item>
      <title>At a loss for blog topics</title>
      <description>&lt;p&gt;For the life of me, I can't seem to come up with any new blogging topics. At this point, I've exhausted all that's in MVC Preview 3, and haven't been doing anything super fun or cool at work lately. Hmmm, toss some things out and maybe I'll come up with something. Anyone?&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;On the flip side, I've fallen in love with &lt;a href="http://twitter.com/matthawley" target="_blank"&gt;Twitter&lt;/a&gt; - allows me to output my thoughts immediately.&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/eworldui?a=iNYH7jt-C6M:kZdnxNLfggs:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/eworldui?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/eworldui?a=iNYH7jt-C6M:kZdnxNLfggs:D7DqB2pKExk"&gt;&lt;img src="http://feeds.feedburner.com/~ff/eworldui?i=iNYH7jt-C6M:kZdnxNLfggs:D7DqB2pKExk" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/eworldui/~4/iNYH7jt-C6M" height="1" width="1"/&gt;</description>
      <link>http://feedproxy.google.com/~r/eworldui/~3/iNYH7jt-C6M/post.aspx</link>
      <author>matthaw</author>
      <comments>http://blog.eworldui.net/post/2008/06/At-a-loss-for-blog-topics.aspx#comment</comments>
      <guid isPermaLink="false">http://blog.eworldui.net/post.aspx?id=8be8f56b-883c-457d-ab7a-bde9a14a7799</guid>
      <pubDate>Sat, 21 Jun 2008 01:36:37 -0800</pubDate>
      <category>General</category>
      <dc:publisher>matthaw</dc:publisher>
      <pingback:server>http://blog.eworldui.net/pingback.axd</pingback:server>
      <pingback:target>http://blog.eworldui.net/post.aspx?id=8be8f56b-883c-457d-ab7a-bde9a14a7799</pingback:target>
      <slash:comments>5</slash:comments>
      <trackback:ping>http://blog.eworldui.net/trackback.axd?id=8be8f56b-883c-457d-ab7a-bde9a14a7799</trackback:ping>
      <wfw:comment>http://blog.eworldui.net/post/2008/06/At-a-loss-for-blog-topics.aspx#comment</wfw:comment>
      <wfw:commentRss>http://blog.eworldui.net/syndication.axd?post=8be8f56b-883c-457d-ab7a-bde9a14a7799</wfw:commentRss>
    <feedburner:origLink>http://blog.eworldui.net/post.aspx?id=8be8f56b-883c-457d-ab7a-bde9a14a7799</feedburner:origLink></item>
    <item>
      <title>Entity Framework Rant</title>
      <description>&lt;p&gt;&amp;lt;rant&amp;gt;&lt;/p&gt;  &lt;p&gt;Wow, I never thought I'd hate a product so badly just starting to use it. If you've not tried out the new Entity Framework, give it a shot - but be ready to get frustrated and fast. The mere fact that I have to do half of my editing in pure XML and the other half in the designer is absurd. Why doesn't the designer support creating a new entity from my pre-loaded entity set from the database, or the ability to add a new property to my entity! Having to hop over to XML view just to add a new property is painful. I'm also all for "iterations" of code, but why is it when it's generating the model during compile time does it only give me 1 error at a time. Gar! I can't stand this - back to LINQ to SQL.&lt;/p&gt;  &lt;p&gt;&amp;lt;/rant&amp;gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/eworldui?a=qNCQqKGTCFY:8V4XSwxvizI:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/eworldui?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/eworldui?a=qNCQqKGTCFY:8V4XSwxvizI:D7DqB2pKExk"&gt;&lt;img src="http://feeds.feedburner.com/~ff/eworldui?i=qNCQqKGTCFY:8V4XSwxvizI:D7DqB2pKExk" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/eworldui/~4/qNCQqKGTCFY" height="1" width="1"/&gt;</description>
      <link>http://feedproxy.google.com/~r/eworldui/~3/qNCQqKGTCFY/post.aspx</link>
      <author>matthaw</author>
      <comments>http://blog.eworldui.net/post/2008/06/Entity-Framework-Rant.aspx#comment</comments>
      <guid isPermaLink="false">http://blog.eworldui.net/post.aspx?id=26b811be-730d-4c9a-a906-419d24763432</guid>
      <pubDate>Tue, 10 Jun 2008 08:54:58 -0800</pubDate>
      <category>.NET</category>
      <dc:publisher>matthaw</dc:publisher>
      <pingback:server>http://blog.eworldui.net/pingback.axd</pingback:server>
      <pingback:target>http://blog.eworldui.net/post.aspx?id=26b811be-730d-4c9a-a906-419d24763432</pingback:target>
      <slash:comments>11</slash:comments>
      <trackback:ping>http://blog.eworldui.net/trackback.axd?id=26b811be-730d-4c9a-a906-419d24763432</trackback:ping>
      <wfw:comment>http://blog.eworldui.net/post/2008/06/Entity-Framework-Rant.aspx#comment</wfw:comment>
      <wfw:commentRss>http://blog.eworldui.net/syndication.axd?post=26b811be-730d-4c9a-a906-419d24763432</wfw:commentRss>
    <feedburner:origLink>http://blog.eworldui.net/post.aspx?id=26b811be-730d-4c9a-a906-419d24763432</feedburner:origLink></item>
    <item>
      <title>Plea for Help: WCF 404 Error</title>
      <description>&lt;p&gt;I'm putting out a plea for help. For some odd reason, we have a WCF service (running in IIS 6) that's using streaming and BasicHttpBinding that will return a 404 error message every time it's called from our client. Hitting the same URL on the box itself through IE renders the WSDL just fine. If you have seen this issue, please contact me. We've been struggling with this issue and have yet to find a resolution. BTW, it works great on another web server that is configured the same, and we've looked at all of the verbose logs WCF can give us. Ultimately, we're seeing the message being sent from the client, and a 404 in the IIS log, but nothing on the server logging. Thanks!&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/eworldui?a=4-NM_LJC0Bg:vGQB-WiuY6U:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/eworldui?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/eworldui?a=4-NM_LJC0Bg:vGQB-WiuY6U:D7DqB2pKExk"&gt;&lt;img src="http://feeds.feedburner.com/~ff/eworldui?i=4-NM_LJC0Bg:vGQB-WiuY6U:D7DqB2pKExk" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/eworldui/~4/4-NM_LJC0Bg" height="1" width="1"/&gt;</description>
      <link>http://feedproxy.google.com/~r/eworldui/~3/4-NM_LJC0Bg/post.aspx</link>
      <author>matthaw</author>
      <comments>http://blog.eworldui.net/post/2008/06/Plea-for-Help-WCF-404-Error.aspx#comment</comments>
      <guid isPermaLink="false">http://blog.eworldui.net/post.aspx?id=61b52a8d-0b96-4564-95bf-ebef96f0e403</guid>
      <pubDate>Fri, 06 Jun 2008 20:33:39 -0800</pubDate>
      <category>Development</category>
      <category>.NET</category>
      <dc:publisher>matthaw</dc:publisher>
      <pingback:server>http://blog.eworldui.net/pingback.axd</pingback:server>
      <pingback:target>http://blog.eworldui.net/post.aspx?id=61b52a8d-0b96-4564-95bf-ebef96f0e403</pingback:target>
      <slash:comments>5</slash:comments>
      <trackback:ping>http://blog.eworldui.net/trackback.axd?id=61b52a8d-0b96-4564-95bf-ebef96f0e403</trackback:ping>
      <wfw:comment>http://blog.eworldui.net/post/2008/06/Plea-for-Help-WCF-404-Error.aspx#comment</wfw:comment>
      <wfw:commentRss>http://blog.eworldui.net/syndication.axd?post=61b52a8d-0b96-4564-95bf-ebef96f0e403</wfw:commentRss>
    <feedburner:origLink>http://blog.eworldui.net/post.aspx?id=61b52a8d-0b96-4564-95bf-ebef96f0e403</feedburner:origLink></item>
    <item>
      <title>MVC Post-Redirect-Get Sample Updated</title>
      <description>&lt;p&gt;I took some time to look back at my MVC Post-Redirect-Get sample and see where it could be improved as well as update it to use the MVC Preview 3 bits. What I found, is again, the core concepts didn't change that much. However, there are some new enhancements that Preview 3 gave us that makes our life a little bit easier. I'll save the full implementation for you to download and checkout yourself, but I do want to highlight some of these enhancements that made the source easier to use.    &lt;br /&gt;    &lt;br /&gt;&lt;font color="#ff8000" size="2"&gt;&lt;strong&gt;1.&lt;/strong&gt;&lt;/font&gt; NameValueCollectionExtensions.CopyTo - this made it very nice for me to take all of the posted form data and copy it into the TempData so that upon a redirect, I could extract it out and put it in ViewData. &lt;/p&gt;  &lt;div class="csharpcode"&gt;   &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   1:  &lt;/span&gt;&lt;span class="kwrd"&gt;if&lt;/span&gt; (!BaseValidator.Validate(HttpContext.Request, validators)) {&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   2:  &lt;/span&gt;   NameValueCollectionExtensions.CopyTo(Request.Form, TempData);&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   3:  &lt;/span&gt;   TempData[&lt;span class="str"&gt;&amp;quot;ErrorMessage&amp;quot;&lt;/span&gt;] = BuildErrorMessage(validators);&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   4:  &lt;/span&gt;   &lt;span class="kwrd"&gt;return&lt;/span&gt; RedirectToAction(&lt;span class="str"&gt;&amp;quot;Create&amp;quot;&lt;/span&gt;);&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   5:  &lt;/span&gt;}&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;&lt;font color="#ff8000" size="2"&gt;&lt;strong&gt;2.&lt;/strong&gt;&lt;/font&gt; I added an extension method for IDictionary&lt;string  , object&gt; to copy between a source and destination, primarily for copying my TempData to ViewData. This way there is no need to do a manual copy of TempData objects all over the place, and is more resilient to changes and additions within your views and controller actions. I'm hoping this makes it into the MVC stack at some point so we all don't have to write this code ourselves.&lt;/p&gt;

&lt;div class="csharpcode"&gt;
  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   1:  &lt;/span&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; CopyTo(&lt;span class="kwrd"&gt;this&lt;/span&gt; IDictionary&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;, &lt;span class="kwrd"&gt;object&lt;/span&gt;&amp;gt; source, &lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   2:  &lt;/span&gt;                          IDictionary&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;, &lt;span class="kwrd"&gt;object&lt;/span&gt;&amp;gt; destination)&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   3:  &lt;/span&gt;{&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   4:  &lt;/span&gt;    &lt;span class="kwrd"&gt;foreach&lt;/span&gt; (KeyValuePair&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;, &lt;span class="kwrd"&gt;object&lt;/span&gt;&amp;gt; pair &lt;span class="kwrd"&gt;in&lt;/span&gt; source)&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   5:  &lt;/span&gt;    {&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   6:  &lt;/span&gt;        &lt;span class="kwrd"&gt;if&lt;/span&gt; (!destination.ContainsKey(pair.Key))&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   7:  &lt;/span&gt;            destination.Add(pair.Key, pair.Value);&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   8:  &lt;/span&gt;    }&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   9:  &lt;/span&gt;}&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;The above code allows us to simply call the following line of code&lt;/p&gt;

&lt;div class="csharpcode"&gt;
  &lt;pre&gt;&lt;span class="lnum"&gt;   1:  &lt;/span&gt;TempData.CopyTo(ViewData);&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;&lt;font color="#ff8000" size="2"&gt;&lt;strong&gt;3.&lt;/strong&gt;&lt;/font&gt; What you'll notice, is that now all of my data is within ViewData, I can start to utilize the built-in functionality added in Preview 3 where the form controls will attempt to extract an initial value from ViewData. This mechanism really brings back the concept of ViewState, except that there is really no overhead to do this! Here's how my form now looks&lt;/p&gt;

&lt;div class="csharpcode"&gt;
  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   1:  &lt;/span&gt;&lt;span class="asp"&gt;&amp;lt;%@ Import Namespace=&amp;quot;PRG.Controllers&amp;quot; %&amp;gt;&lt;/span&gt;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   2:  &lt;/span&gt;&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;asp:Content&lt;/span&gt; &lt;span class="attr"&gt;ID&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;Content1&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;ContentPlaceHolderID&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;MainContent&amp;quot;&lt;/span&gt; &lt;span class="attr"&gt;runat&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;server&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   3:  &lt;/span&gt;&lt;span class="asp"&gt;&amp;lt;%&lt;/span&gt; &lt;span class="kwrd"&gt;using&lt;/span&gt; (Html.Form&amp;lt;ProductsController&amp;gt;(c =&amp;gt; c.Submit())) { &lt;span class="asp"&gt;%&amp;gt;&lt;/span&gt;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   4:  &lt;/span&gt;    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;h3&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;Create a New Product&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;h3&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   5:  &lt;/span&gt;    Name: &lt;span class="asp"&gt;&amp;lt;%&lt;/span&gt;= Html.TextBox(&lt;span class="str"&gt;&amp;quot;Name&amp;quot;&lt;/span&gt;) &lt;span class="asp"&gt;%&amp;gt;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;br&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   6:  &lt;/span&gt;    Price: &lt;span class="asp"&gt;&amp;lt;%&lt;/span&gt;= Html.TextBox(&lt;span class="str"&gt;&amp;quot;Price&amp;quot;&lt;/span&gt;) &lt;span class="asp"&gt;%&amp;gt;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;br&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   7:  &lt;/span&gt;    Quantity: &lt;span class="asp"&gt;&amp;lt;%&lt;/span&gt;= Html.TextBox(&lt;span class="str"&gt;&amp;quot;Quantity&amp;quot;&lt;/span&gt;) &lt;span class="asp"&gt;%&amp;gt;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;br&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   8:  &lt;/span&gt;    &lt;span class="asp"&gt;&amp;lt;%&lt;/span&gt; &lt;span class="kwrd"&gt;if&lt;/span&gt; (ViewData[&lt;span class="str"&gt;&amp;quot;ErrorMessage&amp;quot;&lt;/span&gt;] != &lt;span class="kwrd"&gt;null&lt;/span&gt;) { &lt;span class="asp"&gt;%&amp;gt;&lt;/span&gt;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   9:  &lt;/span&gt;        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;br&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;span&lt;/span&gt; &lt;span class="attr"&gt;style&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;color:red&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;span class="asp"&gt;&amp;lt;%&lt;/span&gt;= ViewData[&lt;span class="str"&gt;&amp;quot;ErrorMessage&amp;quot;&lt;/span&gt;] &lt;span class="asp"&gt;%&amp;gt;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;span&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;br&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  10:  &lt;/span&gt;    &lt;span class="asp"&gt;&amp;lt;%&lt;/span&gt; } &lt;span class="asp"&gt;%&amp;gt;&lt;/span&gt;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  11:  &lt;/span&gt;    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;br&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  12:  &lt;/span&gt;    &lt;span class="asp"&gt;&amp;lt;%&lt;/span&gt;= Html.SubmitButton() &lt;span class="asp"&gt;%&amp;gt;&lt;/span&gt;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  13:  &lt;/span&gt;&lt;span class="asp"&gt;&amp;lt;%&lt;/span&gt; } &lt;span class="asp"&gt;%&amp;gt;&lt;/span&gt;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  14:  &lt;/span&gt;&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;asp:Content&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;&lt;font color="#ff8000" size="2"&gt;&lt;strong&gt;4.&lt;/strong&gt;&lt;/font&gt; While this next item isn't specifically related to Preview 3, it is a change from my last sample. Previously, I was doing all of my manual validations inline on the server, and it wasn't pretty. As you've probably been reading, I've been making some improvements to the MVC Validation within MvcContrib, and I decided I'd bring in that codebase to this sample. However, to truly show the full PRG pattern, I needed my form to post and alert me that there are errors on the page rather than relying upon client side validation; so I'm simply using the validator objects &amp;amp; server validation. In the next coming weeks, I'll be making another update to MvcContrib to do model based validation. I'll leave this code for your viewing or other examples on my blog. 

  &lt;br /&gt;

  &lt;br /&gt;And that's the updated sample. You can downloaded the latest bits &lt;a href="http://www.eworldui.net/files/MvcDemos/PRG.zip"&gt;from here&lt;/a&gt;. Please let me know what you think and anything else you would do to change this. As each iteration of the MVC framework is released, the sample gets easier and easier! Hope you enjoy this.&lt;/p&gt;

&lt;br /&gt;

&lt;br /&gt;&lt;a href="http://www.dotnetkicks.com/kick/?url=http%3a%2f%2fblog.eworldui.net%2fpost%2f2008%2f06%2fMVC-Post-Redirect-Get-Sample-Updated.aspx"&gt;&lt;img alt="kick it on DotNetKicks.com" src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fblog.eworldui.net%2fpost%2f2008%2f06%2fMVC-Post-Redirect-Get-Sample-Updated.aspx" border="0" /&gt;&lt;/a&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/eworldui?a=2PaCzAZB3Bk:_yxkPKeXUrE:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/eworldui?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/eworldui?a=2PaCzAZB3Bk:_yxkPKeXUrE:D7DqB2pKExk"&gt;&lt;img src="http://feeds.feedburner.com/~ff/eworldui?i=2PaCzAZB3Bk:_yxkPKeXUrE:D7DqB2pKExk" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/eworldui/~4/2PaCzAZB3Bk" height="1" width="1"/&gt;</description>
      <link>http://feedproxy.google.com/~r/eworldui/~3/2PaCzAZB3Bk/post.aspx</link>
      <author>matthaw</author>
      <comments>http://blog.eworldui.net/post/2008/06/MVC-Post-Redirect-Get-Sample-Updated.aspx#comment</comments>
      <guid isPermaLink="false">http://blog.eworldui.net/post.aspx?id=d5d84746-b58a-4a20-809d-a28301b742e1</guid>
      <pubDate>Thu, 05 Jun 2008 08:56:05 -0800</pubDate>
      <category>ASP.NET</category>
      <category>.NET</category>
      <category>Development</category>
      <category>MVC</category>
      <category>Programming</category>
      <dc:publisher>matthaw</dc:publisher>
      <pingback:server>http://blog.eworldui.net/pingback.axd</pingback:server>
      <pingback:target>http://blog.eworldui.net/post.aspx?id=d5d84746-b58a-4a20-809d-a28301b742e1</pingback:target>
      <slash:comments>46</slash:comments>
      <trackback:ping>http://blog.eworldui.net/trackback.axd?id=d5d84746-b58a-4a20-809d-a28301b742e1</trackback:ping>
      <wfw:comment>http://blog.eworldui.net/post/2008/06/MVC-Post-Redirect-Get-Sample-Updated.aspx#comment</wfw:comment>
      <wfw:commentRss>http://blog.eworldui.net/syndication.axd?post=d5d84746-b58a-4a20-809d-a28301b742e1</wfw:commentRss>
    <feedburner:origLink>http://blog.eworldui.net/post.aspx?id=d5d84746-b58a-4a20-809d-a28301b742e1</feedburner:origLink></item>
  </channel>
</rss>
