<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-601462402497771325</id><updated>2011-12-19T07:32:32.118-06:00</updated><category term='C#'/><category term='web slices'/><category term='MVC StoreFront'/><category term='SiteFinity'/><category term='charity'/><category term='SOAP Fault'/><category term='form data'/><category term='books'/><category term='asp.net'/><category term='routing'/><category term='Flex'/><category term='Give Camp'/><category term='httphandler'/><category term='manning'/><category term='IE 8'/><category term='We Are Microsoft'/><category term='web services'/><category term='SWF'/><category term='Ebay'/><category term='mvccontrib'/><category term='ASP.NET MVC'/><category term='HTTP POST'/><category term='Flex PMD'/><title type='text'>Ubiquitous Technology</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://ubiquitous-tech.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/601462402497771325/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://ubiquitous-tech.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Magnus Lassi</name><uri>http://www.blogger.com/profile/14911837506908005554</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>15</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-601462402497771325.post-1784881761784413811</id><published>2009-09-06T15:47:00.004-05:00</published><updated>2009-09-06T17:15:59.067-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Flex PMD'/><category scheme='http://www.blogger.com/atom/ns#' term='Flex'/><title type='text'>Flex PMD - improve your code quality</title><content type='html'>I recently started to look into the &lt;a href="http://opensource.adobe.com/wiki/display/flexpmd/FlexPMD"&gt;Flex PMD&lt;/a&gt; open source project. It's supposed to help you analyze your Flex/AS3 code and help you see coding issues that may need to be fixed.&lt;br /&gt;&lt;br /&gt;You can either just use the default ruleset for analyzing your code or create your own custom ruleset. There's an &lt;a href="http://opensource.adobe.com/svn/opensource/flexpmd/bin/flex-pmd-ruleset-creator.html"&gt;editor &lt;/a&gt;you can use to view the default ruleset which also describes each rule and shows examples of a code snippet which would cause it to be applied. You can also change the severity you want to apply when you run Flex PMD or remove rules you don't want to include in the project.&lt;br /&gt;&lt;br /&gt;For example, in a current project I wanted to make sure that all custom events are overriding the clone function. If you drill down to the missing clone function rule, you can see a detailed description and example where it will be applied.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_91cj7CN2IRk/SqQuTkNzTLI/AAAAAAAAAGQ/XqNr3-BEyNA/s1600-h/PMD_Ruleset_Creator.png"&gt;&lt;img style="cursor: pointer; width: 400px; height: 244px;" src="http://4.bp.blogspot.com/_91cj7CN2IRk/SqQuTkNzTLI/AAAAAAAAAGQ/XqNr3-BEyNA/s400/PMD_Ruleset_Creator.png" alt="" id="BLOGGER_PHOTO_ID_5378474768661171378" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;When you are done, you can easily export the ruleset if you have made any changes to it.&lt;br /&gt;&lt;br /&gt;Once you're ready to run it, you have to download either the command line, ant or the maven version. I decided to use ant and there's a good &lt;a href="http://opensource.adobe.com/wiki/display/flexpmd/How+to+invoke+FlexPMD"&gt;example &lt;/a&gt;that you can build from easily.&lt;br /&gt;&lt;br /&gt;An XML file is generated as output and you can either read it directly or use the online &lt;a href="http://opensource.adobe.com/svn/opensource/flexpmd/bin/flex-pmd-violations-viewer.html"&gt;PMD Violations Viewer&lt;/a&gt; which shows you the result graphically.&lt;br /&gt;&lt;br /&gt;If we want to see any custom events with a missing clone function, you can just drill down to the "EventMissingCloneFunction" and you'll see any events with a missing clone function.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_91cj7CN2IRk/SqQuPPW8zrI/AAAAAAAAAGI/KvEXnYhBdYA/s1600-h/PMD_Ruleset_Analyzor.png"&gt;&lt;img style="cursor: pointer; width: 400px; height: 244px;" src="http://3.bp.blogspot.com/_91cj7CN2IRk/SqQuPPW8zrI/AAAAAAAAAGI/KvEXnYhBdYA/s400/PMD_Ruleset_Analyzor.png" alt="" id="BLOGGER_PHOTO_ID_5378474694342921906" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Flex PMD really seems powerful but pretty simple to start using it.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/601462402497771325-1784881761784413811?l=ubiquitous-tech.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ubiquitous-tech.blogspot.com/feeds/1784881761784413811/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=601462402497771325&amp;postID=1784881761784413811' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/601462402497771325/posts/default/1784881761784413811'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/601462402497771325/posts/default/1784881761784413811'/><link rel='alternate' type='text/html' href='http://ubiquitous-tech.blogspot.com/2009/09/flex-pmd-improve-your-code-quality.html' title='Flex PMD - improve your code quality'/><author><name>Magnus Lassi</name><uri>http://www.blogger.com/profile/14911837506908005554</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_91cj7CN2IRk/SqQuTkNzTLI/AAAAAAAAAGQ/XqNr3-BEyNA/s72-c/PMD_Ruleset_Creator.png' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-601462402497771325.post-5160156576069090598</id><published>2009-07-19T15:27:00.006-05:00</published><updated>2009-07-19T16:40:31.823-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='routing'/><category scheme='http://www.blogger.com/atom/ns#' term='mvccontrib'/><category scheme='http://www.blogger.com/atom/ns#' term='ASP.NET MVC'/><title type='text'>Test ASP.NET MVC routes using MVC Contrib</title><content type='html'>Last &lt;a href="http://ubiquitous-tech.blogspot.com/2009/05/routes-in-aspnet-mvc.html"&gt;time&lt;/a&gt; I showed one alternative way of testing routes using Moq and NUnit. It works well but it adds code bloat. The &lt;a href="http://www.codeplex.com/MVCContrib"&gt;MVC Contrib&lt;/a&gt; project has a nice set of test helper methods which simplifies it.&lt;br /&gt;&lt;br /&gt;It assumes you use NUnit and RhinoMocks. It also assumes you set your routes in the ASP.NET MVC RouteCollection object. If you reference your routes in your test project like I do, then this shouldn't be a big issue either.&lt;br /&gt;&lt;br /&gt;Our previous test method looked like this:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:csharp"&gt;&lt;br /&gt;[Test]&lt;br /&gt;public void Test_If_Product_Route_Returns_Expected_Result()&lt;br /&gt;{&lt;br /&gt; RouteCollection routes = new RouteCollection();&lt;br /&gt; POC_Stuff.MvcApplication.RegisterRoutes(routes);&lt;br /&gt;&lt;br /&gt; var context = MvcMockHelpers.FakeHttpContext("~/products/videogames/nintendo");&lt;br /&gt; RouteData routeData = routes.GetRouteData(context);&lt;br /&gt;&lt;br /&gt; Assert.That(routeData.Values["category"].ToString() == "videogames");&lt;br /&gt; Assert.That(routeData.Values["subcategory"].ToString() == "nintendo");&lt;br /&gt; Assert.That(routeData.Values["controller"].ToString() == "Catalog");&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The new test method using the MVC Contrib test helpers will look like this:&lt;br /&gt;&lt;pre class="brush:csharp"&gt;&lt;br /&gt;[Test]&lt;br /&gt;public void Test_If_Product_Route_Returns_Expected_Result()&lt;br /&gt;{&lt;br /&gt;  "~/products/videogames/nintendo".ShouldMapTo&lt;CatalogController&gt;(x =&gt; x.Index("videogames", "nintendo"));&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;I don't think you can make it much more compact! It will even do the assertions for you, the test helper will assert the route data, the controller, the method and its parameters. If you want to make additional asserts, that is possible as well since it returns a RouteData object from the System.Web.Routing namespace.&lt;br /&gt;&lt;br /&gt;The main test class in the MVC Contrib project is called &lt;a href="http://code.google.com/p/mvccontrib/source/browse/trunk/src/MVCContrib.UnitTests/TestHelper/RouteTestingExtensionsTester.cs?spec=svn769&amp;amp;r=769"&gt;RouteTestingExtensions&lt;/a&gt;and the method that will assert the route for us is called ShouldMapTo and the code as of when this post was written looks like this:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:csharp"&gt;&lt;br /&gt;/// &lt;summary&gt;&lt;br /&gt;/// Asserts that the route matches the expression specified.  Checks controller, action, and any method arguments&lt;br /&gt;/// into the action as route values.&lt;br /&gt;/// &lt;/summary&gt;&lt;br /&gt;/// &lt;typeparam name="TController"&gt;The controller.&lt;/typeparam&gt;&lt;br /&gt;/// &lt;param name="routeData"&gt;The routeData to check&lt;br /&gt;/// &lt;param name="action"&gt;The action to call on TController.&lt;br /&gt;public static RouteData ShouldMapTo&lt;tcontroller&gt;(this RouteData routeData, Expression&lt;func&gt;&lt;tcontroller, actionresult=""&gt;&gt; action)&lt;br /&gt; where TController : Controller&lt;br /&gt;{         &lt;br /&gt; routeData.ShouldNotBeNull("The URL did not match any route");&lt;br /&gt;&lt;br /&gt; //check controller&lt;br /&gt; routeData.ShouldMapTo&lt;TController&gt;();&lt;br /&gt;&lt;br /&gt; //check action&lt;br /&gt; var methodCall = (MethodCallExpression) action.Body;&lt;br /&gt; string actualAction = routeData.Values.GetValue("action").ToString();&lt;br /&gt; string expectedAction = methodCall.Method.Name;&lt;br /&gt; actualAction.AssertSameStringAs(expectedAction);&lt;br /&gt;          &lt;br /&gt; //check parameters&lt;br /&gt; for (int i = 0; i &lt; methodCall.Arguments.Count; i++)&lt;br /&gt; {&lt;br /&gt;    string name = methodCall.Method.GetParameters()[i].Name;&lt;br /&gt;    object value = null;&lt;br /&gt;&lt;br /&gt;    switch ( methodCall.Arguments[ i ].NodeType )&lt;br /&gt;    {&lt;br /&gt;        case ExpressionType.Constant:&lt;br /&gt;           value = ( (ConstantExpression)methodCall.Arguments[ i ] ).Value;&lt;br /&gt;           break;&lt;br /&gt;         case ExpressionType.MemberAccess:&lt;br /&gt;           value = Expression.Lambda(methodCall.Arguments[ i ]).Compile().DynamicInvoke();&lt;br /&gt;           break;&lt;br /&gt;    }   &lt;br /&gt;    value = (value == null ? value : value.ToString());&lt;br /&gt;    routeData.Values.GetValue(name).ShouldEqual(value,"Value for parameter did not match");&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;These doesn't seem to be too many developers in the community talking about this great test helper but I hope you see the value it adds.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/601462402497771325-5160156576069090598?l=ubiquitous-tech.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ubiquitous-tech.blogspot.com/feeds/5160156576069090598/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=601462402497771325&amp;postID=5160156576069090598' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/601462402497771325/posts/default/5160156576069090598'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/601462402497771325/posts/default/5160156576069090598'/><link rel='alternate' type='text/html' href='http://ubiquitous-tech.blogspot.com/2009/07/test-aspnet-mvc-routes-using-mvc.html' title='Test ASP.NET MVC routes using MVC Contrib'/><author><name>Magnus Lassi</name><uri>http://www.blogger.com/profile/14911837506908005554</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-601462402497771325.post-5897436250666048154</id><published>2009-05-25T20:53:00.004-05:00</published><updated>2009-05-25T21:33:59.157-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='routing'/><category scheme='http://www.blogger.com/atom/ns#' term='ASP.NET MVC'/><title type='text'>Routes in ASP.NET MVC</title><content type='html'>The routing enginge that ASP.NET MVC is quite powerful and allows mapping between an URL and the controller and controller action. The routing was originally released in ASP.NET 3.5 SP 1 but I suspect few use it with WebForms. You can easily add new routes and have multiple different routes.&lt;br /&gt;&lt;br /&gt;As an example, let's assume we want to have a route where we easily can list various products and also a separate route for events that we offer during various dates. A good piece of advice by Scott Hanselman is to add a comment above your route to make it more clear what the expected route is which I normally do. All the routes are normally wired in the global.asax.&lt;br /&gt;&lt;br /&gt;Our first route to display a subcategory will look like this: http://localhost/product/videogames/nintendo . The crafted route will look like this.&lt;br /&gt;&lt;pre class="brush:csharp"&gt;&lt;br /&gt;// http://localhost/product/category/subcategory&lt;br /&gt;  // http://localhost/product/videogames/nintendo   &lt;br /&gt;  routes.MapRoute(&lt;br /&gt;           "Category",                                              // Route name&lt;br /&gt;           "products/{category}/{subcategory}",                           // URL with parameters&lt;br /&gt;           new&lt;br /&gt;           {&lt;br /&gt;               controller = "Catalog", action = "Index", category = "Listed",&lt;br /&gt;               subcategory = "All Items"&lt;br /&gt;           }&lt;br /&gt;       );&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;We added defaults for the controller, action, category and subcategory but of course that is optional. Our controllers will accept the category and subcategory and act on it.&lt;br /&gt;&lt;br /&gt;Our controller class will need to get the category and subcategory to be able to act on it. Our controller in this example looks like this:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:csharp"&gt;&lt;br /&gt;public class CatalogController : Controller&lt;br /&gt;{&lt;br /&gt;   //&lt;br /&gt;   // GET: /Catalog/&lt;br /&gt;&lt;br /&gt;   public ActionResult Index(string category, string subcategory)&lt;br /&gt;   {&lt;br /&gt;       ViewData["Message"] = string.Format("Category {0}, Subcategory{1}"&lt;br /&gt;                                       , category, subcategory);&lt;br /&gt;       return View();&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;In our next route, we want it to be displaying a specific event on a specific date and as an example it will look like this: http://localhost/events/2009/05/25 . We will craft it like this:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:csharp"&gt;&lt;br /&gt;    // http://localhost/events/year/month/day&lt;br /&gt;   // http://localhost/events/2009/05/25   &lt;br /&gt;   routes.MapRoute(&lt;br /&gt;           "Event",                                              // Route name&lt;br /&gt;           "events/{year}/{month}/{day}",                           // URL with parameters&lt;br /&gt;           new&lt;br /&gt;           {&lt;br /&gt;               controller = "Event",&lt;br /&gt;               action = "Index"&lt;br /&gt;           }&lt;br /&gt;       );      &lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;A corresponding controller that will be handling this request has to be able to handle the year, month and day:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:csharp"&gt;&lt;br /&gt;public class EventController : Controller&lt;br /&gt;{&lt;br /&gt;   //&lt;br /&gt;   // GET: /Event/&lt;br /&gt;&lt;br /&gt;   public ActionResult Index(string year, string month, string day)&lt;br /&gt;   {&lt;br /&gt;       ViewData["Message"] = string.Format("Event for mm {0} / dd {1} / yyyy {2}"&lt;br /&gt;                                         , month, day, year);&lt;br /&gt;       return View();&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;If you have many routes set up, it may be difficult to figure out why a route isn't being executed as expected. I hope most people by now are familiar with Phil Haack's excellent &lt;a href="http://haacked.com/archive/2008/03/13/url-routing-debugger.aspx"&gt;URL Routing Debugger&lt;/a&gt;. &lt;br /&gt;&lt;br /&gt;If we try to hit our product URL by incorrectly specifying the URL http://localhost/product, the Routing Debugger shows that the expected route is not being routed correctly.&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_91cj7CN2IRk/ShtPkIgcZpI/AAAAAAAAAFk/kjj2sedfn1I/s1600-h/RouteDebugger.png"&gt;&lt;img style="cursor: pointer; width: 400px; height: 234px;" src="http://2.bp.blogspot.com/_91cj7CN2IRk/ShtPkIgcZpI/AAAAAAAAAFk/kjj2sedfn1I/s400/RouteDebugger.png" alt="" id="BLOGGER_PHOTO_ID_5339949265355302546" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;This can save a ton of time if you have many routes set up in the same project.&lt;br /&gt;&lt;br /&gt;The one thing we're still missing is unit tests. We should have started with the unit tests but in this example we're showing the example in reverse order to make the routing mechanism more clear. The ASP.NET MVC framework supports many different unit test and mocking frameworks, I prefer the combination of NUnit and Moq but you can use any of the other supported .Net unit testing/mocking frameworks.&lt;br /&gt;&lt;br /&gt;In order to test the routing mechanism, we need to be able to mock the HttpContext. I prefer to use the class &lt;a href="http://www.hanselman.com/blog/ASPNETMVCSessionAtMix08TDDAndMvcMockHelpers.aspx"&gt;MvcMockHelpers&lt;/a&gt;that Scott Hanselman has blogged about instead of writing it from scratch. Our test case for the product route will be quite simple since the plumbing is already done:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:csharp"&gt;&lt;br /&gt;using System;&lt;br /&gt;using System.Web;&lt;br /&gt;using System.Web.Routing;&lt;br /&gt;using Moq;&lt;br /&gt;using NUnit.Framework;&lt;br /&gt;&lt;br /&gt;[TestFixture]&lt;br /&gt;public class RouteTest&lt;br /&gt;{&lt;br /&gt;    [Test]&lt;br /&gt;    public void Test_If_Product_Route_Returns_Expected_Result()&lt;br /&gt;    {&lt;br /&gt;        RouteCollection routes = new RouteCollection();&lt;br /&gt;        POC_Stuff.MvcApplication.RegisterRoutes(routes);&lt;br /&gt;&lt;br /&gt;        var context = MvcMockHelpers.FakeHttpContext("~/products/videogames/nintendo");&lt;br /&gt;        RouteData routeData = routes.GetRouteData(context);&lt;br /&gt;&lt;br /&gt;        Assert.That(routeData.Values["category"].ToString() == "videogames");&lt;br /&gt;        Assert.That(routeData.Values["subcategory"].ToString() == "nintendo");&lt;br /&gt;        Assert.That(routeData.Values["controller"].ToString() == "Catalog");&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;We call the RegisterRoute method of the Global.asax to get the actual routes. After we get the fake HttpContext with our URL, we just need to verify if we see the expected result.&lt;br /&gt;&lt;br /&gt;There are other ways to set up the routing with some of the other frameworks like MvcContrib which we will look at next time.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/601462402497771325-5897436250666048154?l=ubiquitous-tech.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ubiquitous-tech.blogspot.com/feeds/5897436250666048154/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=601462402497771325&amp;postID=5897436250666048154' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/601462402497771325/posts/default/5897436250666048154'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/601462402497771325/posts/default/5897436250666048154'/><link rel='alternate' type='text/html' href='http://ubiquitous-tech.blogspot.com/2009/05/routes-in-aspnet-mvc.html' title='Routes in ASP.NET MVC'/><author><name>Magnus Lassi</name><uri>http://www.blogger.com/profile/14911837506908005554</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_91cj7CN2IRk/ShtPkIgcZpI/AAAAAAAAAFk/kjj2sedfn1I/s72-c/RouteDebugger.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-601462402497771325.post-3904202628187358525</id><published>2009-05-10T14:08:00.003-05:00</published><updated>2009-05-10T17:41:30.853-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='form data'/><category scheme='http://www.blogger.com/atom/ns#' term='ASP.NET MVC'/><category scheme='http://www.blogger.com/atom/ns#' term='HTTP POST'/><title type='text'>ASP.NET MVC - Post to controllers</title><content type='html'>When you first start out using the ASP.NET MVC framework, it might not be apparent the many different ways you can solve the same problem. One example of this is when you want to post form data from a view to a controller.&lt;br /&gt;&lt;br /&gt;Most of the official examples when the ASP.NET MVC framework was in early preview showed how to use the HttpRequest object to gather the form data inside the controller.&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:csharp"&gt;&lt;br /&gt;public ActionResult Edit()&lt;br /&gt;{&lt;br /&gt;    SalesOrderForm form = new SalesOrderForm();&lt;br /&gt; &lt;br /&gt;    string customerName = Request.Form["CustomerName"];&lt;br /&gt;    string address = Request.Form["CustomerAddress"];&lt;br /&gt;    string orderNumber = Request.Form["OrderNumber"];&lt;br /&gt;&lt;br /&gt;    return View(form);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;In this way, you can use the Request object and pull the data out. I don't like to tie the controller directly to the HttpRequest object without any abstraction and I really dislike having use magic strings. It brings back not so fond memories of classical ASP for those that have used the Microsoft stack long enough. Thankfully, very few examples uses this way of gathering the form data.&lt;br /&gt;&lt;br /&gt;An alternative way to pass the form data is to create an action method in the controller which will accept the values posted from the view. The view form fields must match the same names in the controller. A subset of our view shows the fields we are concerned with.&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:xml"&gt;&lt;br /&gt;&lt;% using (Html.BeginForm()) { %&gt;&lt;br /&gt;    &lt;fieldset&gt;&lt;br /&gt;        &lt;legend&gt;Fields&lt;/legend&gt;&lt;br /&gt;        &lt;p&gt;&lt;br /&gt;            &lt;label for="Name"&gt;Name:&lt;/label&gt;&lt;br /&gt;            &lt;%= Html.TextBox("CustomerName") %&gt;&lt;br /&gt;        &lt;/p&gt;&lt;br /&gt;        &lt;p&gt;&lt;br /&gt;           &lt;label for="Address"&gt;Address:&lt;/label&gt;&lt;br /&gt;           &lt;%= Html.TextBox("Address") %&gt;&lt;br /&gt;        &lt;/p&gt;&lt;br /&gt;        &lt;p&gt;&lt;br /&gt;            &lt;label for="OrderNumber"&gt;OrderNumber:;&lt;/label&gt;&lt;br /&gt;            &lt;%= Html.TextBox("OrderNumber") %&gt;&lt;br /&gt;        &lt;/p&gt;&lt;br /&gt;    &lt;/fieldset&gt;&lt;br /&gt;    &lt;p&gt;&lt;br /&gt;        &lt;input type="submit" value="Save" /&gt;&lt;br /&gt;    &lt;/p&gt;&lt;br /&gt;    &lt;% } %&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The controller action method must have matching variable names. The action method is pretty simple in our case and we just need the matching variable names.&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:csharp"&gt;&lt;br /&gt;[AcceptVerbs(HttpVerbs.Post)]&lt;br /&gt;public ActionResult Edit(string customerName, string address, string orderNumber)&lt;br /&gt;{&lt;br /&gt;   &lt;br /&gt;    string myCustomerName = customerName;&lt;br /&gt;    string myAddress = address;&lt;br /&gt;    string orderNumber = orderNumber;&lt;br /&gt;&lt;br /&gt;    // Persist the data into our repository&lt;br /&gt;&lt;br /&gt;    return View();&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;It's a pretty simple exercise to match them but quickly gets unruly if we have more than a handful of parameters we need to pass in. Thankfully, there are a few better ways to handle it. In the next scenario we will use the FormCollection object and use the MVC framework to map it to a view model.&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:csharp"&gt;&lt;br /&gt;public class SalesOrderForm&lt;br /&gt;{&lt;br /&gt;    public string CustomerName { get; set; }&lt;br /&gt;    public string Address { get; set; }&lt;br /&gt;    public string OrderNumber { get; set; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:csharp"&gt;&lt;br /&gt;[AcceptVerbs(HttpVerbs.Post)]&lt;br /&gt;public ActionResult Edit(FormCollection formCol)&lt;br /&gt;{&lt;br /&gt;    SalesOrderForm form = new SalesOrderForm();&lt;br /&gt;&lt;br /&gt;    UpdateModel(form);&lt;br /&gt;    &lt;br /&gt;    // Persist to our repository&lt;br /&gt;&lt;br /&gt;    return View(form);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Our action method only needs to accept the FormCollection object. We instantiate our view model object and call the UpdateModel method which is method of the base class System.Web.Mvc.Controller. Any controller class that you create using the Visual Studio MVC template is subclassed from it and have this method available. Through reflection, it converts between the properties and the form data passed in. This gives us a pretty clean way of mapping the form data to our view model.&lt;br /&gt;&lt;br /&gt;There is an even cleaner way to map the form data to a view model.&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:csharp"&gt;&lt;br /&gt;[AcceptVerbs(HttpVerbs.Post)]&lt;br /&gt;public ActionResult Edit([Bind(Prefix = "")]SalesOrderForm salesForm)&lt;br /&gt;{&lt;br /&gt;    // Persist to the repository&lt;br /&gt;&lt;br /&gt;    return View(salesForm);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;By using the Bind attribute, the controller will attempt to match up the properties with the form data. I think this is the cleanest way to map between the view and the view model and this is the way I usually handle form data that is posted to the controllers.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/601462402497771325-3904202628187358525?l=ubiquitous-tech.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ubiquitous-tech.blogspot.com/feeds/3904202628187358525/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=601462402497771325&amp;postID=3904202628187358525' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/601462402497771325/posts/default/3904202628187358525'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/601462402497771325/posts/default/3904202628187358525'/><link rel='alternate' type='text/html' href='http://ubiquitous-tech.blogspot.com/2009/05/aspnet-mvc-post-to-controllers.html' title='ASP.NET MVC - Post to controllers'/><author><name>Magnus Lassi</name><uri>http://www.blogger.com/profile/14911837506908005554</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-601462402497771325.post-4868039746913598358</id><published>2009-04-14T19:34:00.014-05:00</published><updated>2009-05-09T20:55:47.372-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><category scheme='http://www.blogger.com/atom/ns#' term='HTTP POST'/><category scheme='http://www.blogger.com/atom/ns#' term='SOAP Fault'/><title type='text'>Handling SOAP faults with HttpWebResponse object</title><content type='html'>When you call web services, in normal cases you would use the web service proxy objects that gets generated when you add a web reference and not send in an HTTP POST to the web service. I had an interest case recently where we had to build a test client that accepted invalid SOAP requests with malformed XML as well as well-formed SOAP requests.&lt;br /&gt;&lt;br /&gt;If the web service returns a normal response, we can handle the response and just parse the returned XML. The code is what you would expect&lt;br /&gt;&lt;pre class="brush:csharp"&gt; &lt;br /&gt;try&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;WebResponse webResponse = webRequest.GetResponse();&lt;br /&gt;&lt;br /&gt;if (webResponse != null)&lt;br /&gt;{&lt;br /&gt;StreamReader sr = new StreamReader(webResponse.GetResponseStream());&lt;br /&gt;response = sr.ReadToEnd().Trim();&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;catch (Exception ex)&lt;br /&gt;{&lt;br /&gt;// Handle the request&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;However, if the web service throws a SOAP fault when we try to get the response, the stack trace of the exception will not return the SOAP fault that you would expect. Instead we just a fairly generic error message and an HTTP 500 Internal Server error.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_91cj7CN2IRk/SeVD76ONHcI/AAAAAAAAAFc/wP4THMTKQh8/s1600-h/quickwatch.gif"&gt;&lt;img style="cursor: pointer; width: 400px; height: 221px;" src="http://4.bp.blogspot.com/_91cj7CN2IRk/SeVD76ONHcI/AAAAAAAAAFc/wP4THMTKQh8/s400/quickwatch.gif" alt="" id="BLOGGER_PHOTO_ID_5324736830955658690" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;What's going on? If we use a HTTP sniffer to see the actual raw response we get some clues.&lt;br /&gt;&lt;pre class="brush:text"&gt; &lt;br /&gt;HTTP/1.1 500 Server Error&lt;br /&gt;Server: Sun-ONE-Web-Server/6.1&lt;br /&gt;Date: Wed, 15 Apr 2009 00:42:33 GMT&lt;br /&gt;Content-length: 978&lt;br /&gt;Content-type: text/xml; charset=utf-8&lt;br /&gt;X-Powered-By: Servlet/2.4 JSP/2.0&lt;br /&gt;X-Charles-Received-Continue: HTTP/1.1 100 Continue&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;pre class="brush:xml"&gt; &lt;br /&gt;&lt;soapenv:envelope soapenv="http://schemas.xmlsoap.org/soap/envelope/"&gt;&lt;soapenv:header v1="http://acme.com/ws/customerorder/v1"&gt;&lt;soapenv:body v1="http://acme.com/ws/customerorder/v1"&gt;&lt;soapenv:fault&gt;&lt;faultcode&gt;soapenv:Server&lt;/faultcode&gt;&lt;faultstring&gt;Schema validation failed for request.&lt;/faultstring&gt;&lt;detail&gt;&lt;con:fault con="http://www.bea.com/wli/sb/context"&gt;&lt;con:errorcode&gt;5&lt;/con:errorcode&gt;&lt;br /&gt;&lt;con:reason&gt;Schema validation failed for request.&lt;/con:reason&gt;&lt;con:details&gt;&lt;con1:validationfailuredetail con1="http://www.appserver.com/wc/sb//config"&gt;&lt;br /&gt;&lt;con1:message&gt;string value 'MVP_CUSTOMER' is not a valid enumeration value for CustomerType in namespace&lt;br /&gt;http://acme.com/ws/customerorder/v1&lt;/con1:message&gt;&lt;con1:xmllocation&gt;&lt;v1:customertype&gt;MVP_CUSTOMER&lt;/v1:customertype&gt;&lt;/con1:xmllocation&gt;&lt;/con1:validationfailuredetail&gt;&lt;/con:details&gt;&lt;/con:fault&gt;&lt;/detail&gt;&lt;/soapenv:fault&gt;&lt;/soapenv:body&gt;&lt;/soapenv:header&gt;&lt;br /&gt;&lt;/soapenv:envelope&gt;&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;It's apparent that the web server interprets a SOAP fault as an HTTP 500 error so it has nothing to do with HttpWebResponse class doing something invalid. When we sniffed the HTTP traffic, we could see the detailed SOAP fault information so why can't see it when we catch an exception?&lt;br /&gt;&lt;br /&gt;We need to catch a WebException and then cast the WebException.Response into an HttpWebResponse object. Once we have a valid HttpWebResponse object, we can read the response stream and get the SOAP fault information out. We can then extract the information and turn it into a useful error messages for the logfile or the users.&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:csharp"&gt; &lt;br /&gt;try&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;WebResponse webResponse = webRequest.GetResponse();&lt;br /&gt;&lt;br /&gt;if (webResponse != null)&lt;br /&gt;{&lt;br /&gt;    StreamReader sr = new StreamReader(webResponse.GetResponseStream());&lt;br /&gt;    response = sr.ReadToEnd().Trim();&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;catch (WebException wex)&lt;br /&gt;{&lt;br /&gt;// We issued an HttpWebRequest, so the response will be an&lt;br /&gt;// HttpWebResponse.&lt;br /&gt;HttpWebResponse httpResponse = wex.Response as HttpWebResponse;&lt;br /&gt;&lt;br /&gt;// Grab the response stream.           &lt;br /&gt;using (Stream responseStream = httpResponse.GetResponseStream())&lt;br /&gt;{&lt;br /&gt;   using (StreamReader reader = new StreamReader(responseStream))&lt;br /&gt;   {&lt;br /&gt;       // Grab the body of the response as a string for parsing.&lt;br /&gt;       string failureReason = reader.ReadToEnd();&lt;br /&gt;&lt;br /&gt;       // If it failed with a SOAP fault, parse the response body into a usable exception.&lt;br /&gt;       ThrowIfSoapFault(failureReason);&lt;br /&gt;&lt;br /&gt;       // If it was not a SOAP fault, rethrow the original exception.&lt;br /&gt;       throw;&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Most of the code shown in this example can be found at &lt;a href="http://msdn.microsoft.com/en-us/library/cc540447.aspx"&gt;MSDN&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/601462402497771325-4868039746913598358?l=ubiquitous-tech.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ubiquitous-tech.blogspot.com/feeds/4868039746913598358/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=601462402497771325&amp;postID=4868039746913598358' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/601462402497771325/posts/default/4868039746913598358'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/601462402497771325/posts/default/4868039746913598358'/><link rel='alternate' type='text/html' href='http://ubiquitous-tech.blogspot.com/2009/04/handling-soap-faults-with.html' title='Handling SOAP faults with HttpWebResponse object'/><author><name>Magnus Lassi</name><uri>http://www.blogger.com/profile/14911837506908005554</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_91cj7CN2IRk/SeVD76ONHcI/AAAAAAAAAFc/wP4THMTKQh8/s72-c/quickwatch.gif' height='72' width='72'/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-601462402497771325.post-8053247209105085946</id><published>2009-04-05T16:07:00.007-05:00</published><updated>2009-04-05T20:13:37.627-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SWF'/><category scheme='http://www.blogger.com/atom/ns#' term='SiteFinity'/><title type='text'>SiteFinity - using SWF files</title><content type='html'>I've finally had a chance to continue with my POC to try to integrate my SWF file into SiteFinity. It went pretty smoothly but there was quite a bit of manual work. I haven't had a chance to look at version 3.6 of SiteFinity yet, I hope later versions would have a control that would handle the browser initialization of the SWF file and helping take care of the reference to the SWF file.&lt;br /&gt;&lt;br /&gt;I've heard a lot of buzz about &lt;a href="http://code.google.com/p/swfobject/"&gt;swfobject &lt;/a&gt;which is a JavaScript based framework that instantiates Flash based content regardless of browser, I decided to try it out to see how I would like it. After working for a Fortune 500 company, you learn to worry about what license any open source projects uses, swfobject uses the MIT license which is a plus. It has a nice wizard that will help you set up the appropriate attributes which really helps when you're unfamiliar how to use it in the beginning.&lt;br /&gt;&lt;br /&gt;In SiteFinity, the only way I have found from my initial research is to add it to the Master Page. Hopefully there's a better way than to be forced to have the user get the JavaScript downloaded to the browser or have to add a custom user control if you just have a handful of pages where you use SWF files. I decided to just link to the Google Code repository but you probably want to include it in your website in production scenarios.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_91cj7CN2IRk/SdlFmhyG7dI/AAAAAAAAAFE/-UhIYcK0UqQ/s1600-h/MasterPageAddSWFObject.gif"&gt;&lt;img style="cursor: pointer; width: 400px; height: 62px;" src="http://4.bp.blogspot.com/_91cj7CN2IRk/SdlFmhyG7dI/AAAAAAAAAFE/-UhIYcK0UqQ/s400/MasterPageAddSWFObject.gif" alt="" id="BLOGGER_PHOTO_ID_5321360962920836562" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;I just uploaded my SWF file to the Files section in SiteFinity and then added it via an OBJECT tag in a Generic Control. I have not been able the get the file reference of the SWF file to be resolved inside the OBJECT so I can use a relative reference like for the server side controls in SiteFinity. Instead, I've had to put the full URL to the file which is a pain point if you have separate QA and Production environments. It appears that others in the SiteFinity forums also have struggled with this but hopefully I'm just overlooking something.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_91cj7CN2IRk/SdlO2ATBCnI/AAAAAAAAAFM/TE1fr5ajmZ0/s1600-h/GenericContentSWHTML.gif"&gt;&lt;img style="cursor: pointer; width: 400px; height: 273px;" src="http://1.bp.blogspot.com/_91cj7CN2IRk/SdlO2ATBCnI/AAAAAAAAAFM/TE1fr5ajmZ0/s400/GenericContentSWHTML.gif" alt="" id="BLOGGER_PHOTO_ID_5321371124414614130" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The actual page shows the SWF file as we would expect.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_91cj7CN2IRk/SdlWRfL88hI/AAAAAAAAAFU/3leeHPU8Pp4/s1600-h/AuctionSWF.gif"&gt;&lt;img style="cursor: pointer; width: 400px; height: 180px;" src="http://1.bp.blogspot.com/_91cj7CN2IRk/SdlWRfL88hI/AAAAAAAAAFU/3leeHPU8Pp4/s400/AuctionSWF.gif" alt="" id="BLOGGER_PHOTO_ID_5321379293144347154" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;It is a relatively easy process to add a SWF to SiteFinity but hopefully there will be an easier way to add it in the future and control it better.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/601462402497771325-8053247209105085946?l=ubiquitous-tech.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ubiquitous-tech.blogspot.com/feeds/8053247209105085946/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=601462402497771325&amp;postID=8053247209105085946' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/601462402497771325/posts/default/8053247209105085946'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/601462402497771325/posts/default/8053247209105085946'/><link rel='alternate' type='text/html' href='http://ubiquitous-tech.blogspot.com/2009/04/sitefinity-using-swf-files.html' title='SiteFinity - using SWF files'/><author><name>Magnus Lassi</name><uri>http://www.blogger.com/profile/14911837506908005554</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_91cj7CN2IRk/SdlFmhyG7dI/AAAAAAAAAFE/-UhIYcK0UqQ/s72-c/MasterPageAddSWFObject.gif' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-601462402497771325.post-8941517521889540778</id><published>2009-03-21T16:35:00.007-05:00</published><updated>2009-03-22T10:47:42.282-05:00</updated><title type='text'>eBay integration in Flex</title><content type='html'>Work has been quite demanding lately but hopefully I will be able to post more regularly now.&lt;br /&gt;&lt;br /&gt;I had planned to integrate eBay into SiteFinity via custom user controls but I decided to instead write the integration in Flex and integrate that into SiteFinity. It will make it easier for my client to add new versions since I only need to give them the SWF file and they can upload it themselves. I already know that we will need to support both search functionality for eBay auctions and ability to list items for auction and possibly other types of functionality. I decided to create a POC first and integrate that into SiteFinity before adding more interesting functionality. I focused on getting the infrastructure set up before making it look spiffy. In this post I'll show how to create the Flex binary. The SWF and source code has been posted &lt;a href="http://texmags.110mb.com/AuctionManager/AuctionManager.html"&gt;here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_91cj7CN2IRk/ScV59zVd8pI/AAAAAAAAAE0/Kb_WhK78zeE/s1600-h/SearchManager.gif"&gt;&lt;img style="cursor: pointer; width: 400px; height: 158px;" src="http://4.bp.blogspot.com/_91cj7CN2IRk/ScV59zVd8pI/AAAAAAAAAE0/Kb_WhK78zeE/s400/SearchManager.gif" alt="" id="BLOGGER_PHOTO_ID_5315789037839970962" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;I decided to use one of the Flex MVC frameworks because I already know I will need to support several screens and it will make it easier to support. I picked the &lt;a href="http://mate.asfusion.com/"&gt;Mate &lt;/a&gt;framework, because it fits so nicely into Flex and it's non-intrusive. Mate strongly encourages you to separate the logic into views, event maps, events and business objects  shown below.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_91cj7CN2IRk/ScZdSbBD72I/AAAAAAAAAE8/zRsSNaR3Wm8/s1600-h/ProjectStructure.gif"&gt;&lt;img style="cursor: pointer; width: 281px; height: 343px;" src="http://1.bp.blogspot.com/_91cj7CN2IRk/ScZdSbBD72I/AAAAAAAAAE8/zRsSNaR3Wm8/s400/ProjectStructure.gif" alt="" id="BLOGGER_PHOTO_ID_5316038981228687202" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The communication between the view and event handlers is handled via the &lt;a href="http://mate.asfusion.com/assets/content/diagrams/two_way_view_injection.png"&gt;Event Bus&lt;/a&gt;. An event is dispatched from the view and the event bus figures out which event map that listens for the event that was dispatched. The event map calls services and/or business objects. Commonly the event map also have injectors that binds properties in the view to business objects.&lt;br /&gt;&lt;br /&gt;The event map in my POC is relatively simple displayed below.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_91cj7CN2IRk/ScV11x6kkiI/AAAAAAAAAEk/VYpkIY4vK9A/s1600-h/SearchEventMap.gif"&gt;&lt;img style="cursor: pointer; width: 400px; height: 255px;" src="http://3.bp.blogspot.com/_91cj7CN2IRk/ScV11x6kkiI/AAAAAAAAAEk/VYpkIY4vK9A/s400/SearchEventMap.gif" alt="" id="BLOGGER_PHOTO_ID_5315784501973258786" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;This event map listens for the event SearchRequestEvent.GET and calls a business class SearchInvoker. This class makes a call to eBay using their Flash based API and dispatches either a success event or a fault event that gets handled inside the event map.&lt;br /&gt;&lt;br /&gt;The event map also has Injectors that sets up the binding between properties in the view to the SearchManager. These injectors are initialized first before any custom events gets dispatched from the view.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_91cj7CN2IRk/ScV3T6k5-ZI/AAAAAAAAAEs/Y2_gkTaL_yk/s1600-h/SearchInjectors.gif"&gt;&lt;img style="cursor: pointer; width: 400px; height: 41px;" src="http://4.bp.blogspot.com/_91cj7CN2IRk/ScV3T6k5-ZI/AAAAAAAAAEs/Y2_gkTaL_yk/s400/SearchInjectors.gif" alt="" id="BLOGGER_PHOTO_ID_5315786119206009234" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The next step will be to add the SWF to SiteFinity.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/601462402497771325-8941517521889540778?l=ubiquitous-tech.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ubiquitous-tech.blogspot.com/feeds/8941517521889540778/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=601462402497771325&amp;postID=8941517521889540778' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/601462402497771325/posts/default/8941517521889540778'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/601462402497771325/posts/default/8941517521889540778'/><link rel='alternate' type='text/html' href='http://ubiquitous-tech.blogspot.com/2009/03/ebay-integration-in-flex.html' title='eBay integration in Flex'/><author><name>Magnus Lassi</name><uri>http://www.blogger.com/profile/14911837506908005554</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_91cj7CN2IRk/ScV59zVd8pI/AAAAAAAAAE0/Kb_WhK78zeE/s72-c/SearchManager.gif' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-601462402497771325.post-2716046771491712107</id><published>2009-02-14T08:59:00.004-06:00</published><updated>2009-02-14T09:04:45.719-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='books'/><category scheme='http://www.blogger.com/atom/ns#' term='manning'/><title type='text'>Manning rocks!</title><content type='html'>It seems like everyone is getting a bad customer experience these days. I bought a &lt;a href="http://www.manning.com/about/meap.html"&gt;MEAP &lt;/a&gt;early access book from Manning last year called "Unlocking Facebook". In October, the author wrote that Manning had cancelled the book. I was going to contact Manning but you can only contact them by calling them so I gave up. This week they sent me an email and let me have a refund OR two books of same type! Now that is great customer service!&lt;br /&gt;&lt;br /&gt;I'm going to be busy reading &lt;a href="http://www.manning.com/kuate/"&gt;Nhibernate In Action&lt;/a&gt; and &lt;a href="http://www.manning.com/palermo/"&gt;ASP.NET MVC In Action&lt;/a&gt; now. Good stuff.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/601462402497771325-2716046771491712107?l=ubiquitous-tech.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ubiquitous-tech.blogspot.com/feeds/2716046771491712107/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=601462402497771325&amp;postID=2716046771491712107' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/601462402497771325/posts/default/2716046771491712107'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/601462402497771325/posts/default/2716046771491712107'/><link rel='alternate' type='text/html' href='http://ubiquitous-tech.blogspot.com/2009/02/manning-rocks.html' title='Manning rocks!'/><author><name>Magnus Lassi</name><uri>http://www.blogger.com/profile/14911837506908005554</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-601462402497771325.post-6865147391631645797</id><published>2009-02-07T11:34:00.002-06:00</published><updated>2009-02-08T18:19:50.430-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='web services'/><category scheme='http://www.blogger.com/atom/ns#' term='Ebay'/><title type='text'>Taking a look at the Ebay API's</title><content type='html'>Work has been quite challenging as of late but I finally have some spare time on the weekends again. One of my planned tasks have been to integrate Ebay listings into SiteFinity. This was something that our charity originally requested during the charity event in January but we never got to it. Now after I've had a chance to look into Ebay's API, I can tell it would have been impossible unless I had known then what I know now about their API's.&lt;br /&gt;&lt;br /&gt;Ebay has a developer &lt;a href="http://developer.ebay.com/"&gt;web site&lt;/a&gt; which describes all the various API's they have available and sample code. They have different types of &lt;a href="http://developer.ebay.com/products/overview/api-by-feature/"&gt;API's&lt;/a&gt; depending on what I intend to do, i.e. if you want to sell or buy or look at historical data and so forth. They also have a number of different stacks you can use depending on your platform: library based, SOAP based, XML over HTTP and REST. Their site is a little messy and I couldn't find anywhere where they show all the options you have, you have to dig around. I decided to use the Trading API based on what I am interesting in doing and decided to use the SOAP API.&lt;br /&gt;&lt;br /&gt;I first downloaded the SDK for .Net with samples to take a quick look. Apparently, all the samples appears to be using their library. Surprisingly, the samples were built with VS 2003/.Net 1.1 and it was not a smooth process to VS 2008/.Net 3.5. Apparently they have a dependency on the J# Redistributable Package so I had to search their forums and download the Redistributable Package just to be able to even compile the sample. Bad customer experience. However, they have some samples that are more up-to-date in the Knowledgebase and other sections at their developer web site.&lt;br /&gt;&lt;br /&gt;I'm a little surprised how companies like Ebay and Amazon appear to be pushing their libraries if you want to integrate with them. Is that what developers actually ask for or is it just a bad idea conceived by someone in their marketing departments? I don't like to add a dependency on a third party library unless it has a compelling set of features that really makes everything so much easier. In this case because it appears that they want to have some of the assemblies in the GAC and my code will be hosted at a hosting provider, it seemed like a bad idea to me. Maybe I haven't looked into it in enough depth but I don't see that it's much easier than just using one of their other API's directly.&lt;br /&gt;&lt;br /&gt;I decided to either to use their SOAP API or their REST API. I'm inclined to call their "REST" API a &lt;a href="http://duncan-cragg.org/blog/post/strest-service-trampled-rest-will-break-web-20/"&gt;STREST &lt;/a&gt;API since it's not resource based at all, you just dump the request at one service endpoint which really defeats the purpose of using REST.  Their SOAP API is not a lot better, it consists of one single massive 4 MB WSDL file. Their API's just seem to be based on their old XML over HTTP technology and the only thing that is different if you use a different API is the notation. You have to specify both the operation you want to invoke and the authentication in the service endpoint like this:&lt;br /&gt;&lt;br /&gt;https://api.ebay.com/&lt;br /&gt;wsapi?callname=AddItem&amp;amp;siteid=0&amp;amp;appid=myappid&amp;amp;version=511&amp;amp;Routing=new&lt;br /&gt;&lt;br /&gt;This is a poor design IMO, there's no reason why they can't derive the operation and authentication from the message. If you use their SOAP API, you have to specify both authentication and the operation you want to invoke in the SOAP body as well. I'm disappointed in their design decisions and I hope no one uses Ebay as a good example to follow. Frankly, I had expected a lot more based on their good reputation in general.&lt;br /&gt;&lt;br /&gt;If you decide to use their SOAP API or their REST API, I recommend you use a web service testing tool to verify that your calls work correctly instead of having to write a bunch of code and running into issues and either having serialize the request or have to use a HTTP Proxy tool to be able to troubleshoot it. I prefer using &lt;a href="http://www.soapui.org/"&gt;soapUI &lt;/a&gt;because the rich feature set and that they have a free version but there are a number of other tools you can use, I'm not aware of any other free tools though. SoapUI also has a professional version with more features but I have never looked into that. Here's an example of the GetCategories call in soapUI:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_91cj7CN2IRk/SY7-BOgF7NI/AAAAAAAAAEU/XjRn2-pXaeA/s1600-h/soapUI_GetCategories.png"&gt;&lt;img style="cursor: pointer; width: 400px; height: 252px;" src="http://2.bp.blogspot.com/_91cj7CN2IRk/SY7-BOgF7NI/AAAAAAAAAEU/XjRn2-pXaeA/s400/soapUI_GetCategories.png" alt="" id="BLOGGER_PHOTO_ID_5300453108487679186" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;However, some of their other operations are quite complex like AddItem. It might be more benefical to just use a tool like this to easily see all the options instead of trying to get it to run because of the large number of options. Thankfully, they have really good documentation online that describes all the various options and the available values when it's restricted.&lt;br /&gt;&lt;br /&gt;In my case, the operations that are of interest to me is GetCategories to get all the various categories and AddItem which lists an item at Ebay. Now when I have figured out exactly what operations I need to invoke for the functionality I am interested in, I will try to get it to work in SiteFinity.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/601462402497771325-6865147391631645797?l=ubiquitous-tech.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ubiquitous-tech.blogspot.com/feeds/6865147391631645797/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=601462402497771325&amp;postID=6865147391631645797' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/601462402497771325/posts/default/6865147391631645797'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/601462402497771325/posts/default/6865147391631645797'/><link rel='alternate' type='text/html' href='http://ubiquitous-tech.blogspot.com/2009/02/taking-look-at-ebay-apis.html' title='Taking a look at the Ebay API&apos;s'/><author><name>Magnus Lassi</name><uri>http://www.blogger.com/profile/14911837506908005554</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_91cj7CN2IRk/SY7-BOgF7NI/AAAAAAAAAEU/XjRn2-pXaeA/s72-c/soapUI_GetCategories.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-601462402497771325.post-921550837775524920</id><published>2009-01-24T09:37:00.008-06:00</published><updated>2009-01-25T19:05:47.276-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SiteFinity'/><title type='text'>Telerik SiteFinity - first impression</title><content type='html'>At the &lt;a href="http://www.wearemicrosoft.com/WAM/Home.aspx"&gt;We Are Microsoft&lt;/a&gt; charity event last weekend, our team decided to implement a solution using a CMS product so they easily would be able to update the content. We decided to use Telerik SiteFinity based on the repution of Telerik and the fact that they had developer training the first day. Perhaps not the strongest reasons to pick a product but in our case we did not regret picking SiteFinity. The&lt;a href="http://cmswatch.com/CMS/Report/Vendors/"&gt; Web CMS Report&lt;/a&gt; have categorized the most well known CMS products, SiteFinity is categorized "Mid Market Challengers" which from what I can tell is an accurate categorization.&lt;br /&gt;&lt;br /&gt;We used SiteFinity version 3.5 SP 1. The intial setup was a bit painful because the MSI installer didn't work too well on my Vista laptop but thankfully evengalist Gabe Sumner pointed out during the training that you can download a SiteFinity Visual Studio solution from &lt;a href="http://sitefinity.com/my-client.net/my-downloads.aspx"&gt;sitefinity.com&lt;/a&gt; . The solution file is a Visual Studio Web Site template, I would have preferred a Web Application Project but I assume it's easy enough to change if you really want to change it.&lt;br /&gt;&lt;br /&gt;SiteFinity plugs into the regular VS template pretty nicely. You will without a doubt want to add your own master page and the good news is that you just add it like you would in a normal ASP.NET web site. You need to add a script manager in the markup though like this:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_91cj7CN2IRk/SXtXRFROi_I/AAAAAAAAAEE/CGLOQEpq7aQ/s1600-h/ScriptManager_MasterPage.png"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 400px; height: 69px;" src="http://4.bp.blogspot.com/_91cj7CN2IRk/SXtXRFROi_I/AAAAAAAAAEE/CGLOQEpq7aQ/s400/ScriptManager_MasterPage.png" alt="" id="BLOGGER_PHOTO_ID_5294921737887976434" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;You also need to add a theme to the App_Themes folder. This is where you put your css files and images that you use in the header/body/footer via your master page. Once you restart your worker process or the web server if you use Cassini, both the master page (template) and your theme should be visible once you edit a page. If you select a the template and the theme you created earlier, you should get the look and feel your expecting.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_91cj7CN2IRk/SXvNPSLjSSI/AAAAAAAAAEM/yVmLlCWrCSQ/s1600-h/SiteFinityTemplateTheme.png"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 400px; height: 43px;" src="http://2.bp.blogspot.com/_91cj7CN2IRk/SXvNPSLjSSI/AAAAAAAAAEM/yVmLlCWrCSQ/s400/SiteFinityTemplateTheme.png" alt="" id="BLOGGER_PHOTO_ID_5295051449366169890" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;This is the basics to set it up, I will go into more detail after adding more functionality.&lt;br /&gt;&lt;br /&gt;What I like about SiteFinity so far:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;WSIWYI Editor for editing content.&lt;/li&gt;&lt;li&gt;Very easy for non-technical people to learn to use with a little training. Of course, you still need to know some basic HTML to make it look right.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Workflow enginge in the Standard version, which is nice to have. I haven't had a chance to use it yet though.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;User controls hooks into SiteFinity in a nicely, allowing drag-and-drop in the GUI. You do have to add an entry into the web.config file though.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;It's relatively inexpensive, I don't think $899 is much money for a commercial organization for a CMS product where you get support.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;What I don't like:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;All pages appear to use ViewState by default, whether it's static text only or a form. I think ViewState in general is way overused in ASP.NET web forms in general, I wish Telerik didn't fall into this trap as well but perhaps there's a good reason.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;I really don't understand why even images must use an Httphandler ASHX but perhaps it's not as heavy handed as it seems to be.&lt;/li&gt;&lt;li&gt;Error handling seems a little sparse. Both during the setup and if it can't find the database when you run it, you get uncaught exceptions.&lt;/li&gt;&lt;li&gt;ASP.NET 3.5 has been out for a good while now, you expect products to use 3.5 instead of 2.0 by now.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;All in all, I really like this product and I'm glad I got a chance to try it out. The &lt;a href="http://www.sitefinity.com/product/roadmap.aspx"&gt;road map &lt;/a&gt;for version 4 looks pretty interesting. I wish they would have mentioned using the ASP.NET MVC framework instead of the ASP.NET Web Forms though.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/601462402497771325-921550837775524920?l=ubiquitous-tech.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ubiquitous-tech.blogspot.com/feeds/921550837775524920/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=601462402497771325&amp;postID=921550837775524920' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/601462402497771325/posts/default/921550837775524920'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/601462402497771325/posts/default/921550837775524920'/><link rel='alternate' type='text/html' href='http://ubiquitous-tech.blogspot.com/2009/01/telerik-sitefinity-first-impression.html' title='Telerik SiteFinity - first impression'/><author><name>Magnus Lassi</name><uri>http://www.blogger.com/profile/14911837506908005554</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_91cj7CN2IRk/SXtXRFROi_I/AAAAAAAAAEE/CGLOQEpq7aQ/s72-c/ScriptManager_MasterPage.png' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-601462402497771325.post-5581566586118960048</id><published>2009-01-19T20:00:00.004-06:00</published><updated>2009-01-19T21:00:52.872-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='We Are Microsoft'/><category scheme='http://www.blogger.com/atom/ns#' term='Give Camp'/><category scheme='http://www.blogger.com/atom/ns#' term='charity'/><category scheme='http://www.blogger.com/atom/ns#' term='SiteFinity'/><title type='text'>We-Are-Microsoft charity event - wrap-up</title><content type='html'>I just got back from the charity event &lt;a href="http://www.facebook.com/groups/edit.php?members&amp;amp;gid=25590171916#/event.php?eid=44676024865"&gt;We Are Microsoft&lt;/a&gt; hosted in Dallas. It was a wonderful event, so many charities that all were worthwhile causes. I met a bunch of wonderful people, it is amazing that so many people were willing to give up a full weekend away from their families. I think the final tally was over 170 people including developers, designers, charities and event staff. It was very exhausting weekend of coding and little sleep but great to see that all charities actually received a fully working web site. Chris Koenig and Toi Wright put together a really great event plus all the volunteers.&lt;br /&gt;&lt;br /&gt;Our team built a web site for the shelter &lt;a href="http://www.newbeginningcenter.org/"&gt;New Beginning Center&lt;/a&gt; using Telerik Sitefinity as the CMS of choice. The new website isn't quite ready yet but will hopefully be up in the next few weeks as we're working on the finishing touches.&lt;br /&gt;&lt;br /&gt;None of the guys on our team had any prior experience using SiteFinity but thankfully it was relatively easy to use. Telerik also had two great developer evengalists, &lt;a href="http://blogs.telerik.com/GabeSumner/Posts.aspx"&gt;Gabe Sumner&lt;/a&gt; and &lt;a href="http://blogs.telerik.com/ToddAnglin/Posts.aspx"&gt;Todd Anglin&lt;/a&gt; who really knew the product well and were great at providing feedback. I will post later this week what I liked and disliked about SiteFinity.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/601462402497771325-5581566586118960048?l=ubiquitous-tech.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ubiquitous-tech.blogspot.com/feeds/5581566586118960048/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=601462402497771325&amp;postID=5581566586118960048' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/601462402497771325/posts/default/5581566586118960048'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/601462402497771325/posts/default/5581566586118960048'/><link rel='alternate' type='text/html' href='http://ubiquitous-tech.blogspot.com/2009/01/we-are-microsoft-charity-event-wrap-up.html' title='We-Are-Microsoft charity event - wrap-up'/><author><name>Magnus Lassi</name><uri>http://www.blogger.com/profile/14911837506908005554</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-601462402497771325.post-7449624600545781787</id><published>2009-01-04T19:22:00.003-06:00</published><updated>2009-01-04T21:32:17.897-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='MVC StoreFront'/><category scheme='http://www.blogger.com/atom/ns#' term='ASP.NET MVC'/><title type='text'>ASP.NET MVC - StoreFront</title><content type='html'>Like so many others in the .Net community, I've been looking at the ASP.NET &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_0"&gt;MVC&lt;/span&gt; framework lately which as of this writing is currently in beta. I really like what I've seen so far but YMMV. It seems like many  developers that have experience using &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_1"&gt;MonoRail&lt;/span&gt; have raised quite a few concerns. Obviously, &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_2"&gt;MonoRail&lt;/span&gt; has been around for quite a while and have a lot more features and some of the design decisions may make &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_3"&gt;MonoRail&lt;/span&gt; more extensible than ASP.NET &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_4"&gt;MVC&lt;/span&gt; ever will be.&lt;br /&gt;&lt;br /&gt;I've used the User Interface Process (&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_5"&gt;UIP&lt;/span&gt;) Application Block previously in some projects and ASP.NET &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_6"&gt;MVC&lt;/span&gt; is quite impressive compared to &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_7"&gt;UIP&lt;/span&gt; :-). I really like that you can replace the view engine and that the &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_8"&gt;aspx&lt;/span&gt; pages are so much more lightweight compared to Web Forms.&lt;br /&gt;&lt;br /&gt;One of the more fascinating sample applications that I have seen come from Microsoft as long as I can remember is the &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_9"&gt;MVC&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_10"&gt;StoreFront&lt;/span&gt; by Rob &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_11"&gt;Conery&lt;/span&gt;. It is so refreshing to finally see a sample application that has some complexity. It takes quite a bit of time to go through all the video's but is well worth it where Rob goes through using ASP.NET &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_12"&gt;MVC&lt;/span&gt; and concepts like Dependency Injection, TDD, Mocking and even Domain Driven Design. It's a little bit confusing that the first 23 video's are at &lt;a href="http://www.asp.net/learn/mvc-videos/#MVCStorefrontStarterKit"&gt;ASP.NET / &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_13"&gt;MVC&lt;/span&gt;&lt;/a&gt; while also all the previous and new episodes (25 and forward) with topics like Domain Driven Design is at Rob's &lt;a href="http://blog.wekeroad.com/mvc-storefront/"&gt;blog&lt;/a&gt;. There are a ton of good comments at his blog so that's the best place to go to.&lt;br /&gt;&lt;br /&gt;The &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_14"&gt;MVC&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_15"&gt;StoreFront&lt;/span&gt; is just a tremendous learning experience using a variety of frameworks that may be useful in your projects. Extra plus that Rob doesn't just "pimp" Microsoft solutions and educate the use of some OSS frameworks.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/601462402497771325-7449624600545781787?l=ubiquitous-tech.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ubiquitous-tech.blogspot.com/feeds/7449624600545781787/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=601462402497771325&amp;postID=7449624600545781787' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/601462402497771325/posts/default/7449624600545781787'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/601462402497771325/posts/default/7449624600545781787'/><link rel='alternate' type='text/html' href='http://ubiquitous-tech.blogspot.com/2009/01/aspnet-mvc-storefront.html' title='ASP.NET MVC - StoreFront'/><author><name>Magnus Lassi</name><uri>http://www.blogger.com/profile/14911837506908005554</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-601462402497771325.post-5989817113629300315</id><published>2008-12-16T20:19:00.000-06:00</published><updated>2008-12-16T20:19:50.047-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='asp.net'/><category scheme='http://www.blogger.com/atom/ns#' term='IE 8'/><category scheme='http://www.blogger.com/atom/ns#' term='httphandler'/><title type='text'>IE 8 Web Slices - part 2</title><content type='html'>See &lt;a href="http://ubiquitous-tech.blogspot.com/2008/12/ie-8-web-slices-part-1.html"&gt;part 1&lt;/a&gt; for the introduction of this web slice implementation where we set up the order web page. In the order page we showed where we set the RSS feed that we want to point to. In this part we will implement the Httphandler and RSS feed.&lt;br /&gt;&lt;br /&gt;There's plenty of information available on how Httphandlers work, I won't go into the details about that. Our Httphandler listens for requests coming in to our SalesOrderWeb web site that takes the form http://localhost/SalesOrderWeb/123/OrderTracking.rss where "123" is the SalesOrderId of an order in the AdventureWorks database we want to look up.&lt;br /&gt;&lt;br /&gt;The IHttpHandler interface have one method and one property that must be implemented:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;IsReusable&lt;/li&gt;&lt;li&gt;ProcessRequest&lt;/li&gt;&lt;/ul&gt;The IsResuable property has confused many developers due to very sparse documentation about it. It can be set to true if multiple requests can process the HttpHandler at the same time, i.e. we don't have any private data or similar that could inadvertily be shared between two requests that run at the same time. Clear as mud? Good. Our HttpHandler does not have any data that is shared between requests so we can set IsResuable to true.&lt;br /&gt;&lt;br /&gt;The ProcessRequest method will process the requests for us and output the processed data when we are done. This sequence diagram shows roughly the sequence of events that takes place.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_91cj7CN2IRk/SUhg8g4L1EI/AAAAAAAAAD0/YQQAfAWrZHM/s1600-h/ProcessRequest.gif"&gt;&lt;img style="cursor: pointer; width: 400px; height: 295px;" src="http://4.bp.blogspot.com/_91cj7CN2IRk/SUhg8g4L1EI/AAAAAAAAAD0/YQQAfAWrZHM/s400/ProcessRequest.gif" alt="" id="BLOGGER_PHOTO_ID_5280577155825914946" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The actual ProcessRequest method in our HttpHandler looks like this:&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="csharp"&gt;&lt;br /&gt;public void ProcessRequest(HttpContext context)&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;if (ValidateParameters(context) == false) // Not good&lt;br /&gt;{&lt;br /&gt;context.Response.StatusCode = 500;&lt;br /&gt;context.Response.End();&lt;br /&gt;&lt;br /&gt;return;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;string[] requestPath = context.Request.Path.Split((char)'/');&lt;br /&gt;string salesOrderNumber = requestPath[2];&lt;br /&gt;&lt;br /&gt;FeedChannel chan = new FeedChannel(salesOrderNumber);&lt;br /&gt;string feed = chan.GetRSSFeed();&lt;br /&gt;&lt;br /&gt;context.Response.ContentType = "text/xml";&lt;br /&gt;context.Response.Write(feed);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The first thing we need to do is to validate the input which is handled in the ValidateParameters method. In this sample we're just checking that we have what appears to be a SalesOrderId and then we get the salesOrderId out of the request.&lt;br /&gt;&lt;br /&gt;Next, we instantiate the FeedChannel which loads the SalesHeader and SalesDetail for this sales order and we build the html that will be displayed in the "Description" field in the RSS item. In this implementation we only will have one single FeedItem but it's possible to have more than one FeedItem for every channel if you have aggregate data that you want to display in your feed.&lt;br /&gt;&lt;br /&gt;We call the GetRSSFeed method which will create the XML we want to output and display in the web slice. We use the XmlDocument in .Net and the associated classes to help build the request in this case.&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" code="csharp"&gt;&lt;br /&gt;public string GetRSSFeed()&lt;br /&gt;{         &lt;br /&gt; XmlElement workNode = null;&lt;br /&gt; XmlElement itemNode = null;&lt;br /&gt;&lt;br /&gt; // Get the custom section which contains the default values for the RSS feed.&lt;br /&gt; SalesOrderConfigSection soSection = SalesOrderConfigSection.GetConfig();&lt;br /&gt;&lt;br /&gt; XmlDocument doc = new XmlDocument();&lt;br /&gt; XmlProcessingInstruction pi =&lt;br /&gt;     doc.CreateProcessingInstruction("xml-stylesheet",&lt;br /&gt;         string.Format("type='text/css' href='http://{0}/SalesOrderWeb/css/rss.css'"&lt;br /&gt;             , Dns.GetHostName()));&lt;br /&gt; doc.AppendChild(pi);&lt;br /&gt;&lt;br /&gt; XmlElement docNode = doc.CreateElement("rss");&lt;br /&gt; XmlAttribute attribute = doc.CreateAttribute("version");&lt;br /&gt; attribute.Value = "2.0";&lt;br /&gt; docNode.Attributes.Append(attribute);&lt;br /&gt; doc.AppendChild(docNode);&lt;br /&gt;&lt;br /&gt; // Create the channel element and its subelements:&lt;br /&gt; XmlElement channelElement = doc.CreateElement("channel");&lt;br /&gt; docNode.AppendChild(channelElement);                     &lt;br /&gt;&lt;br /&gt; AddElement(doc, channelElement, "title", string.Format(_title, SalesOrderId));&lt;br /&gt; AddElement(doc, channelElement, "link", string.Format(soSection.URL,&lt;br /&gt;                             Dns.GetHostName(), SalesOrderId));&lt;br /&gt; AddElement(doc, channelElement, "description", soSection.Description);&lt;br /&gt; AddElement(doc, channelElement, "ttl", soSection.ttl);&lt;br /&gt;&lt;br /&gt; // Add the information about each line item.&lt;br /&gt; foreach (FeedItem feedItem in _feedItems)&lt;br /&gt; {&lt;br /&gt;     itemNode = doc.CreateElement("item");&lt;br /&gt;     channelElement.AppendChild(itemNode);&lt;br /&gt;     workNode = doc.CreateElement("title");&lt;br /&gt;     workNode.InnerText = string.Format(feedItem.Title, SalesOrderId);&lt;br /&gt;     itemNode.AppendChild(workNode);&lt;br /&gt;     workNode = doc.CreateElement("description");&lt;br /&gt;     workNode.InnerText = feedItem.Description;&lt;br /&gt;     itemNode.AppendChild(workNode);&lt;br /&gt;     workNode = doc.CreateElement("link");&lt;br /&gt;     workNode.InnerText = string.Format(soSection.URL, Dns.GetHostName(), SalesOrderId);&lt;br /&gt;     itemNode.AppendChild(workNode);            &lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; return doc.OuterXml;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The returned xml is written into the HttpResponse, formatted as text/xml and returned to the browser.&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="csharp"&gt;&lt;br /&gt;context.Response.ContentType = "text/xml";&lt;br /&gt;context.Response.Write(feed);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The feed is a fairly normal RSS feed that can be viewed in the browser, in a separate RSS Reader or in the web slice as the intent was in this case.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/601462402497771325-5989817113629300315?l=ubiquitous-tech.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ubiquitous-tech.blogspot.com/feeds/5989817113629300315/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=601462402497771325&amp;postID=5989817113629300315' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/601462402497771325/posts/default/5989817113629300315'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/601462402497771325/posts/default/5989817113629300315'/><link rel='alternate' type='text/html' href='http://ubiquitous-tech.blogspot.com/2008/12/ie-8-web-slices-part-2.html' title='IE 8 Web Slices - part 2'/><author><name>Magnus Lassi</name><uri>http://www.blogger.com/profile/14911837506908005554</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_91cj7CN2IRk/SUhg8g4L1EI/AAAAAAAAAD0/YQQAfAWrZHM/s72-c/ProcessRequest.gif' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-601462402497771325.post-629470545470536694</id><published>2008-12-14T15:48:00.018-06:00</published><updated>2008-12-15T05:47:05.623-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='asp.net'/><category scheme='http://www.blogger.com/atom/ns#' term='IE 8'/><category scheme='http://www.blogger.com/atom/ns#' term='httphandler'/><category scheme='http://www.blogger.com/atom/ns#' term='web slices'/><title type='text'>IE 8 Web Slices - part 1</title><content type='html'>Recently I've been looking at IE 8 and the new features that have been added, web slices and accelerators. They're both useful, web slices in particular since it can be used in any kind of information you want to keep updated like a sales order for example. It also helps that Microsoft has released the features as an open specification, Firefox has an add-on called WebChunks instead of Web Slices.&lt;br /&gt;&lt;br /&gt;In order to really try it out and see if web slices could be useful, I created a small ASP.NET project that has an order page and uses an RSS feed for the web slice, implemented via an ASP.NET Httphandler. The sample project can be downloaded &lt;a href="http://k6zp2q.bay.livefilestore.com/y1pICMtNIPAD1MHoxC2Tkweji0vIl2lbjf-1ctvLAABDzCbz65_YpDT3k_nqyWVRUhZW2lV1VlA02A/SalesOrderWeb.zip?download"&gt;here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;I've split up this into two blog posts because it would be such a lengthy post otherwise. This post is part 1 and explains the order page, part 2 will describe the Httphandler and the RSS feed.&lt;br /&gt;&lt;br /&gt;This is an example of what this web slice looks like in IE 8.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_91cj7CN2IRk/SUWODP99BNI/AAAAAAAAADU/u75289uCPSg/s1600-h/AdvWorksWebSlice121408.png"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 300px; height: 180px;" src="http://1.bp.blogspot.com/_91cj7CN2IRk/SUWODP99BNI/AAAAAAAAADU/u75289uCPSg/s200/AdvWorksWebSlice121408.png" alt="" id="BLOGGER_PHOTO_ID_5279782324638909650" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;This sample was created using C# on Vista / IIS 7, VS 2008 and SQL Server 2008. The database is using the AdventureWorks sample database. If you haven't installed it, you can download it from &lt;a href="http://www.codeplex.com/MSFTDBProdSamples"&gt;here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;I have not used any particular features that require IIS 7 or SQL Server 2008. I strongly recommend that you download and use one of the public Virtual PC 2007 images Microsoft have released that has IE 8 installed instead of installing the IE 8 beta on your main machine.&lt;br /&gt;&lt;br /&gt;If you extract the zip file, you will see the 4 projects the solution contains:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;SalesOrderWeb - main ASP.NET which include the sample order page&lt;/li&gt;&lt;li&gt;SalesOrderRSS - Httphandler and RSS feed logic&lt;/li&gt;&lt;li&gt;DAL - our data layer which retrieves the order information from the database&lt;/li&gt;&lt;li&gt;BusinessEntity - the domain layer, just contains the properties&lt;/li&gt;&lt;/ul&gt;The ASP.NET page only contains one page, Order.aspx. The page will either retrieve a random order from the database or retrieve a specific order if the user is requesting to view the order from the web slice. In our sample, the user will navigate to the same order page but in a real world scenario the user would probably navigate to a different view where they can track the order, contact customer service and so forth.&lt;br /&gt;&lt;br /&gt;The Page_Load method contains the bulk of the work on this page.&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="Cpp"&gt;&lt;br /&gt;protected void Page_Load(object sender, EventArgs e)&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;if (!Page.IsPostBack)&lt;br /&gt;{&lt;br /&gt;string salesOrderId = string.Empty;&lt;br /&gt;DAL.SalesOrder dal = new SalesOrder();&lt;br /&gt;&lt;br /&gt;// If this is an existing order&lt;br /&gt;if (Request.QueryString.Count &gt; 0 &amp;amp;&amp;amp; Request.QueryString["SalesOrderId"] != null)&lt;br /&gt;{&lt;br /&gt;salesOrderId = Request.QueryString["SalesOrderId"].ToString();&lt;br /&gt;}&lt;br /&gt;else&lt;br /&gt;{&lt;br /&gt;salesOrderId = dal.RetrieveRandomSalesOrderId();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;SalesHeader sh = dal.RetrieveSalesOrder(salesOrderId);&lt;br /&gt;_salesHeader = sh;&lt;br /&gt;&lt;br /&gt;GridView1.DataSource = sh.SalesDetails;&lt;br /&gt;GridView1.DataBind();&lt;br /&gt;&lt;br /&gt;labelSalesOrderNumber.Text = salesOrderId;&lt;br /&gt;&lt;br /&gt;// Embed in the page the url of the RSS feed for this sales order.&lt;br /&gt;SetRSSFeedURL(salesOrderId);&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;If we don't have a "SalesOrderId" value in the query string, we will assume this is a new order and we call into our data layer to retrieve a random order from the database. The bulk of the work to retrieve the random order in the DAL can be seen below.&lt;br /&gt;&lt;br /&gt;&lt;pre name="sqlrandom" class="Cpp"&gt;&lt;br /&gt;using (SqlCommand cmd = conn.CreateCommand())&lt;br /&gt;{&lt;br /&gt;cmd.CommandType = System.Data.CommandType.Text;&lt;br /&gt;cmd.CommandText = "SELECT TOP 1 SalesOrderID FROM Sales.SalesOrderHeader ORDER BY NEWID()";&lt;br /&gt;&lt;br /&gt;conn.Open();&lt;br /&gt;&lt;br /&gt;using (SqlDataReader dr = cmd.ExecuteReader(System.Data.CommandBehavior.CloseConnection))&lt;br /&gt;{&lt;br /&gt;while (dr.Read())&lt;br /&gt;{&lt;br /&gt;salesOrderId = dr.GetInt32(0).ToString();&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;The use of the NEWID() SQL Server method is an interesting way to generate a random value like in our case but normally I would generate a random number in the code and not add extra work to the database.&lt;br /&gt;&lt;br /&gt;After we have a SalesOrderId regardless if we retrieved a random sales order or via an existing order, we retrieve the details from the DAL via the &lt;span style="font-family:courier;"&gt; RetrieveSalesOrder&lt;/span&gt; method. It contains quite a few inner joins, normally I would create a stored procedure or view but for ease of setting up this sample I decided to just set the sql in a StringBuilder object.&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="Cpp"&gt;&lt;br /&gt;StringBuilder sqlStatement = new StringBuilder();&lt;br /&gt;sqlStatement.Append("SELECT sh.SalesOrderNumber");&lt;br /&gt;sqlStatement.Append(",sh.[Status]");&lt;br /&gt;sqlStatement.Append(",sh.ShipDate");&lt;br /&gt;sqlStatement.Append(",sh.DueDate");&lt;br /&gt;sqlStatement.Append(",sh.TotalDue");&lt;br /&gt;sqlStatement.Append(",sh.TaxAmt");&lt;br /&gt;sqlStatement.Append(",sh.Freight");&lt;br /&gt;sqlStatement.Append(",sd.LineTotal");&lt;br /&gt;sqlStatement.Append(",sd.OrderQty");&lt;br /&gt;sqlStatement.Append(",p.Name");&lt;br /&gt;sqlStatement.Append(" FROM Sales.SalesOrderHeader sh");&lt;br /&gt;sqlStatement.Append(" INNER JOIN Sales.SalesOrderDetail sd");&lt;br /&gt;sqlStatement.Append(" On sh.SalesOrderId = sd.SalesOrderId");&lt;br /&gt;sqlStatement.Append(" INNER JOIN Production.Product p");&lt;br /&gt;sqlStatement.Append(" On sd.ProductID = p.ProductID");&lt;br /&gt;sqlStatement.AppendFormat(" WHERE sh.SalesOrderId = {0}", salesOrderId);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;After we have retrieved the sales order details, we set the results to the gridview. The DAL returns the domain business classes to the UI. Returning a SqlDataReader or similar one of the worst ways of coupling the database implementation to the presentation. I personally dislike returning a dataset too because it's such a bloated xml mess.&lt;br /&gt;&lt;br /&gt;Finally, we call the &lt;span style="font-family:courier;"&gt;SetRSSFEEDUrl&lt;/span&gt; method to set the RSS feed url for the web slice for this particular order. Because we are using a master page, we need to do a little extra work to find the "feedurl" control where we set the url.&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="Cpp"&gt;&lt;br /&gt;private void SetRSSFeedURL(string salesOrderNumber)&lt;br /&gt;{&lt;br /&gt;// Find the feedurl href so we can set the correct url (RSS feed).&lt;br /&gt;// Since this is on a master page, we have to through some hoops.&lt;br /&gt;ContentPlaceHolder contentPlaceHolder;&lt;br /&gt;&lt;br /&gt;contentPlaceHolder = (ContentPlaceHolder)Master.FindControl("ContentPlaceHolder1");&lt;br /&gt;if (contentPlaceHolder != null)&lt;br /&gt;{&lt;br /&gt;Control ctl = (Control)contentPlaceHolder.FindControl("feedurl");&lt;br /&gt;&lt;br /&gt;if (ctl != null)&lt;br /&gt;{&lt;br /&gt;HtmlAnchor anchor = (HtmlAnchor)ctl;&lt;br /&gt;&lt;br /&gt;if (anchor != null)&lt;br /&gt;{&lt;br /&gt;anchor.HRef = string.Format("http://{0}/SalesOrderWeb/{1}/OrderTracking.rss"&lt;br /&gt;            , System.Net.Dns.GetHostName()&lt;br /&gt;            , salesOrderNumber&lt;br /&gt;             );&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;There are couple of things of interest that we have to set up in the web.config file. We are using a custom configuration section to store the default values for our RSS feed like title, description and so forth. First we define the type at the top of the web.config file like the below configuration shows.&lt;br /&gt;&lt;br /&gt;&lt;textarea name="code" class="Cpp"&gt;&lt;br /&gt;&lt;configuration&gt;&lt;br /&gt;    &lt;configsections&gt;  &lt;br /&gt;        &lt;section name="salesOrderConfigSection" type="SalesOrderRSS.Configuration.SalesOrderConfigSection, SalesOrderRSS, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"&gt;&lt;br /&gt; &lt;/section&gt;&lt;br /&gt;    &lt;/configsections&gt;&lt;br /&gt;&lt;/configuration&gt;&lt;br /&gt;&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;At the bottom of the web.config, we display the default values like this.&lt;br /&gt;&lt;br /&gt;&lt;textarea name="code" class="xml"&gt;&lt;br /&gt;&lt;salesorderconfigsection title="AdventureWorks Sales Order: {0}" description="An example of creating an RSS feed via HTTPHandler using AdventureWorks database." url="http://{0}/SalesOrderWeb/Order.aspx?SalesOrderId={1}" ttl="60"&gt;&lt;br /&gt;&lt;/configuration&gt;&lt;br /&gt;&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;We also set up the connection string to the database using the regular connection string element that was introduced with ASP.NET 2.0&lt;br /&gt;&lt;br /&gt;&lt;textarea name="code" class="xml"&gt;&lt;br /&gt;&lt;connectionstrings&gt;&lt;br /&gt;  &lt;add name="AdvWorksConn" connectionstring="server=(local); Integrated Security=true; Initial Catalog=AdventureWorks;"&gt;&lt;br /&gt; &lt;/connectionstrings&gt;&lt;br /&gt;&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;Lastly, we set up the httphandler. We specify that we only want this handler to fire for GET requests. We also define that it should only run if the URL for this site ends with "OrderTracking.rss". Any other ".rss" handlers will be ignored unless they are listed in the web.config or machine.config. We also set the type where the httphandler can be loaded.&lt;br /&gt;&lt;br /&gt;&lt;textarea name="code" class="xml"&gt;&lt;br /&gt;&lt;system.webserver&gt;&lt;br /&gt;  &lt;handlers&gt;&lt;br /&gt;   &lt;add name="SalesOrder" verb="GET" path="OrderTracking.rss" type="SalesOrderRSS.RSSHandlerSalesOrder, SalesOrderRSS, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"&gt;&lt;br /&gt;  &lt;/handlers&gt;&lt;br /&gt; &lt;/system.webServer&gt;&lt;br /&gt;&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;If we have set everything up correctly and publish the solution to our web site, our order page should look something like this when we "create" a new order.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_91cj7CN2IRk/SUWzQ0R_NTI/AAAAAAAAADk/tlUEKzd0zt0/s1600-h/SalesOrderPage.png"&gt;&lt;img style="cursor: pointer; width: 320px; height: 250px;" src="http://2.bp.blogspot.com/_91cj7CN2IRk/SUWzQ0R_NTI/AAAAAAAAADk/tlUEKzd0zt0/s320/SalesOrderPage.png" alt="" id="BLOGGER_PHOTO_ID_5279823239655142706" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;That's it!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/601462402497771325-629470545470536694?l=ubiquitous-tech.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ubiquitous-tech.blogspot.com/feeds/629470545470536694/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=601462402497771325&amp;postID=629470545470536694' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/601462402497771325/posts/default/629470545470536694'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/601462402497771325/posts/default/629470545470536694'/><link rel='alternate' type='text/html' href='http://ubiquitous-tech.blogspot.com/2008/12/ie-8-web-slices-part-1.html' title='IE 8 Web Slices - part 1'/><author><name>Magnus Lassi</name><uri>http://www.blogger.com/profile/14911837506908005554</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_91cj7CN2IRk/SUWODP99BNI/AAAAAAAAADU/u75289uCPSg/s72-c/AdvWorksWebSlice121408.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-601462402497771325.post-6685081738314817201</id><published>2008-12-06T21:28:00.002-06:00</published><updated>2008-12-06T21:41:08.543-06:00</updated><title type='text'>First post</title><content type='html'>Hello everyone, I will be writing about technological topics that interest me at the moment. I work with a variety of different technologies but will for most part write about Microsoft topics using .Net/C#/ASP.Net/SharePoint and RIA tech like Flex. First up I will show one example of how you can use ASP.NET and the new feature Web slices in IE 8.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/601462402497771325-6685081738314817201?l=ubiquitous-tech.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ubiquitous-tech.blogspot.com/feeds/6685081738314817201/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=601462402497771325&amp;postID=6685081738314817201' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/601462402497771325/posts/default/6685081738314817201'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/601462402497771325/posts/default/6685081738314817201'/><link rel='alternate' type='text/html' href='http://ubiquitous-tech.blogspot.com/2008/12/first-post.html' title='First post'/><author><name>Magnus Lassi</name><uri>http://www.blogger.com/profile/14911837506908005554</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>
