netug-niederrhein.de User Group Meeting

  The user group met today at netzkern, a company in Wuppertal specialized in .net development and SiteCore - thanks the venue and drinks! Thanks to Matthias for the pic! This time we had "Sliverlight 2 in the real world" as a topic presented by Florian Kruesch. He presented new visual features as well as use cases and projects he's working on. Because he didn't touch the non-visual stuff like Isolated Storage he invited me to show something that I've build with the bits: The "Silverlight Cache" for javascript - most commonly used to cache json returned by web services. A lovely way to reduce traffic :-)

UrlAuthorization with ASP.NET Routing

What is life without security. In the last posts I told you how to do URLRewriting with the ASP.NET 3.5 RoutingEngine and how to pass query strings to the destination Web Form. In this post I'll add some authorization code to let ASP.NET Authentication mechanisms play well. The first step is to figure out which authentication mechanism has taken place in the local configuration file. For the case of forms based authentication it would be nice to redirect to the configured login Web Form, for all other authentication mechanisms we can only throw a security exception and set a HTTP status code. I only wanted this operation to be executed once and therefore I implemented as static and thread safe property with a backing field and a lock object:private static string s_authenticationType; private static object s_authenticationTypeLock = new object(); private static string AuthenticationType { get { if (string.IsNullOrEmpty(s_authenticationType)) { lock (s_authenticationTypeLock) { if (string.IsNullOrEmpty(s_authenticationType)) { var authenticationSectionObject = WebConfigurationManager.GetSection( "system.web/authentication"); var authenticationSection = authenticationSectionObject as AuthenticationSection; if (authenticationSection != null) { s_authenticationType = authenticationSection.Mode.ToString(); } } } } return s_authenticationType; } } .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }   Now its time to check the authorization on the target Web Form:if (httpContext != null && !UrlAuthorizationModule.CheckUrlAccessForPrincipal( VirtualPath, httpContext.User, httpContext.Request.HttpMethod)) { if (AuthenticationType. Equals("forms", StringComparison.OrdinalIgnoreCase)) { VirtualPath = FormsAuthentication.LoginUrl; queryString = new StringBuilder( string.Concat( "?ReturnUrl=", requestContext.HttpContext.Server.UrlEncode( requestContext.HttpContext.Request.RawUrl ))); } else { throw (new SecurityException()); } } .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; } Next I will add a login Web Form to the site and drop a LoginControl to the form: And add some code behind:using System; using System.Web.Security; using System.Web.UI; using System.Web.UI.WebControls; public partial class login : Page { protected void OnLoggingIn(object sender, LoginCancelEventArgs e) { //TODO: add some auth logic or use membership... FormsAuthentication.RedirectFromLoginPage( "lennybacon", false); } } .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; } Authorization requires an authorization and therefore I enable ASP.NET forms based authentication that also is compatible to ASP.NET Membership in the configuration file:<configuration> <system.web> <authentication mode="Forms"/> ... .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }   I can configure the authorization settings for the destination Web Forms are also in the web.config file by adding location sections:<configuration> ... <location path="Default2.aspx"> <system.web> <authorization> <deny users="?"/> </authorization> </system.web> </location> ... .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }   Running the web site and clicking the link to the route (/other) that targets the Default2.aspx results in showing up the login.aspx. Notice that the address bar has not changed - the usual roundtrip for redirecting to the loginURL is also "rewritten" inside of ASP.NET.   This way the security is easily plugged into the RoutingHandler class - Cool stuff! 

ASP.NET Routing for URLRewriting with QueryStrings

In the last post I showed how to use the ASP.NET 3.5 Routing Engine for URLRewriting purposes. I want to go further in this post by adding the ability to add variables into a route path and forward and append query string variables to the destination Web Form request. A route can contain one or more variables expressed by its {name}.  RouteTable.Routes.Add( new Route( "articles/{id}", new devcoach.Web.RoutingPageHandler())); .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }   Inside of the RoutingHandler we can iterate through the variables by accessing them by the RouteData property on the parameter passing the RequestContext:  var queryString = new StringBuilder("?"); foreach (var aux in requestContext.RouteData.Values) { queryString.Append( requestContext.HttpContext.Server.UrlEncode(aux.Key)); queryString.Append("="); queryString.Append( requestContext.HttpContext.Server.UrlEncode( aux.Value.ToString())); queryString.Append("&"); } queryString.Remove(queryString.Length - 1, 1); .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }   The problem now is that the method CreateInstanceFromVirtualPath of the BuildManager class does not allow us to pass for instance a query string as a parameter (I had this discussion recently with Holger at the speakers party of the Basta! confrence):  var handler = (IHttpHandler)BuildManager.CreateInstanceFromVirtualPath( VirtualPath, typeof(Page)); .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }   Passing URL Parameters (a query string) to the instance of the page created from its virtual path we can use the good old RewitePath method (which should be familiar for everyone who has rewritten URLs with ASP.NET 2.0):   HttpContext.Current.RewritePath(    string.Concat(        VirtualPath,        queryString)); var handler =    (IHttpHandler)BuildManager.CreateInstanceFromVirtualPath(        VirtualPath,        typeof(Page));   It feels a bit strange to use the old fashioned way of rewriting URLs just to pass a query string, but the routing handler will stay in control of the request and only the context  variables gets modified.  Listening to: Elbow - Grounds for Divorce

ASP.NET Routing for URLRewiting

With ASP.NET MVC comes a component that is called the routing engine. In ASP.NET MVC it is responsible to assign a controller to an incoming request: From an conceptional view the routing engine consists of two parts: a) The RouteTable which stores the information which routes are defined b) The UrlRoutingModule which finds matches to routes on incoming requests. But the routing engine is not limited to MVC in its use. The ASP.NET 3.5 Routing Engine is a powerful instrument for URLRewriting. Lets have a look how to use routing standalone or with classic ASP.NET (wow, now its already classic! Never dreamed that this would happen so fast... But hey, the .NET platform is nearly ten years old...): 1. First I added the HttpModule to you configuration file: .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; } … <httpModules> <add name="urlRouting" type="System.Web.Routing.UrlRoutingModule, System.Web.Routing, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/> … .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; } 2. Second I created a routing handler by implementing the IRouteHandler interface which comes from System.Web.Routing. I've put a simple if-else together to route to different pages:using System.Web; using System.Web.Compilation; using System.Web.Routing; namespace devcoach.Web { public class RoutingPageHandler : IRouteHandler { public IHttpHandler GetHttpHandler(RequestContext requestContext) { var VirtualPath = pathData.VirtualPath.Contains("articles") ? "~/Default.aspx" : "~/Default2.aspx"; var handler = (IHttpHandler)BuildManager.CreateInstanceFromVirtualPath( VirtualPath, typeof(Page)); return handler; } } }  .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; } 3. Third I registered the routes to the RouteTable from within the Global.asax file: <%@ Import Namespace="devcoach.Web"%><%@ Import Namespace="System.Web.Routing"%><%@ Application Language="C#" %> <script runat="server"> .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; } static void RegisterRoutes() { RouteTable.Routes.Add( new Route( "articles", new RoutingPageHandler())); RouteTable.Routes.Add( new Route( "other", new RoutingPageHandler())); } void Application_Start(object sender, EventArgs e) { RegisterRoutes(); }  And here we go already:  Basic URLRewiting in a few minutes. Quite neat, eh. Definitely worth a try...  Now listening to: Flobots - Handlebars

Simplify LINQ code?

A few days ago a developer at a customer asked me how he could simplify the following code as he identified a pattern: X tries and the error handling. public PlanungsGruppenLesenA PlanungsGruppenLesen(     PlanungsGruppenLesenF param) {     PlanungsGruppenLesenA ret = new PlanungsGruppenLesenA();       if (ret.PlanungsGruppen == null)     {         throw new ArgumentNullException("param.PlanungsGruppen");     }     int nRetry = 0;     while (nRetry < DBWerkzeug.MaxWiederholungen)     {         try         {             using (XXX_POC.POC db =                 new XXX_POC.POC(                     DBWerkzeug.GetConnectionString()))             {                 var q =                     from p in db.Stammdaten_Planungsgruppe                     orderby p.Name.ToLower()                     select new PlanungsGruppeDM                     {                         ID = p.Rowid,                         Name = p.Name                     };                 ret.PlanungsGruppen = q.ToList<PlanungsGruppeDM>();             }         }         catch (ChangeConflictException e)         {             nRetry++;             if (nRetry >= DBWerkzeug.MaxWiederholungen)             {                 ret.FehlerText = e.Message;                 ret.HatFehler = true;                 throw;             }         }         catch (Exception e)         {             ret.FehlerText = e.Message;             ret.HatFehler = true;             throw;         }     }     return ret; } I ended up with this: public PlanungsGruppenLesenA PlanungsGruppenLesen(     PlanungsGruppenLesenF param) {     PlanungsGruppenLesenA ret = new PlanungsGruppenLesenA();       if (ret.PlanungsGruppen == null)     {         throw new ArgumentNullException("param.PlanungsGruppen");     }     ret.PlanungsGruppen = CatchExceptions<PlanungsGruppeDM>(         delegate         {             using (XXX_POC.POC db =                 new XXX_POC.POC(                     DBWerkzeug.GetConnectionString()))             {                 var q =                     from p in db.Stammdaten_Planungsgruppe                     orderby p.Name.ToLower()                     select new PlanungsGruppeDM                     {                         ID = p.Rowid,                         Name = p.Name                     };                 return q.ToList<PlanungsGruppeDM>();             }         },         ret);                return ret; } What calls the encapsulated X tries and the error handling: public delegate List<T> MachMal<T>();   public static List<T> CatchExceptions<T>(MachMal<T> machMichFertig, BasisA ret) {     int nRetry = 0;     while (nRetry < DBWerkzeug.MaxWiederholungen)     {         try         {             return machMichFertig();         }         catch (ChangeConflictException e)         {             nRetry++;             if (nRetry >= DBWerkzeug.MaxWiederholungen)             {                 ret.FehlerText = e.Message;                 ret.HatFehler = true;                 throw;             }         }         catch (Exception e)         {             ret.FehlerText = e.Message;             ret.HatFehler = true;             throw;         }     }     return null; } But I'm not quite sure If this made stuff really easier ;-)

Playing with the Windows RSS Platform

Microsoft introduces with Vista/IE7/Office2007 the Microsoft RSS Platform - For some reasons my IE is not able to export the feeds that I read in IE7 and Outlook 2007 to OPML.I had a look at the API and wrote this small console applictaion to export my feed list to the OPML format. using System; using System.IO; using System.Runtime.InteropServices; using System.Xml;   using Microsoft.Feeds.Interop; using System.Collections.Generic;   namespace RssWindowsPlatformOpmlExporter {     class Program     {         static void Main(string[] args)         {             string pathToExport = "D:\\temp\\feeds.opml";             if (args.Length > 0)             {                 pathToExport = args[0];             }               FeedsManager mgr = new FeedsManager();             Queue<IFeedFolder> queue = new Queue<IFeedFolder>();             queue.Enqueue(mgr.RootFolder as IFeedFolder);               while (queue.Count > 0)             {                 IFeedFolder currentFolder = queue.Dequeue();                 IFeedsEnum subFolders = (IFeedsEnum)currentFolder.Subfolders;                   for (int i = 0; i < subFolders.Count; i++)                 {                     queue.Enqueue((IFeedFolder)subFolders.Item(i));                 }                   using (XmlWriter opml = XmlWriter.Create(pathToExport))                 {                     opml.WriteStartDocument();                     opml.WriteStartElement("opml");                     opml.WriteAttributeString("version", "1.0");                       IFeedsEnum feeds = (IFeedsEnum)currentFolder.Feeds;                     for (int i = 0; i < feeds.Count; i++)                     {                         IFeed feed = (IFeed)feeds.Item(i);                           try                         {                             if (!string.IsNullOrEmpty(feed.Title)                                 && !string.IsNullOrEmpty(feed.DownloadUrl))                             {                                 opml.WriteStartElement("outline");                                 opml.WriteAttributeString("title", feed.Title);                                 opml.WriteAttributeString("xmlUrl", feed.url);                                 opml.WriteEndElement();                             }                         }                         catch (COMException e)                         {                             Console.WriteLine(                                 "Error getting feed: {0}",                                 e.Message);                         }                     }                       opml.WriteEndElement();                     opml.WriteEndDocument();                 }             }         }     } }

TornadoCamp WinFX

thinktecture and newtelligence AG present a week of Windows Communication Foundation (WCF), Windows Presentation Foundation (WPF) and Windows Workflow Foundation (WWF): TornadoCamp WinFX. Christian, Ingo, Michael and me will present from the 16th - 20th of october in Bad Ems in GERMAN!

WCF Sample - Attribute driven Constraints

I posted some Bits Michael and I wrote recently in a WCF Project:The Constraints-Extensions let you easily define attribute based limitations for input, output and return parameters. Limitations can be set to service contracts operations as well as to data contract data member implementations. The constraints validation gets called at runtime by the WCF infrastructure and the behavior will throw a ConstraintViolationException with descriptive messages in case of a constraint gets violated/the validation fails. The following constraint attributes have been implemented:BetweenBetweenExclusiveCompareAgainstEarlierThanNowEarlierThanTodayEqualToGreaterEqualToGreaterThanLaterThanNowLaterThanTodayLessEqualToLessThanMatchMaxElementsMaxLengthMinElementsMinLengthNotBetweenNotEmptyNotEqualToNotNullNullableOneOff·     Data Contract Sample: [DataContract]class TestClass{    [DataMember]    [LessEqualTo(CompareAgainst.FieldOrProperty,"EndDate")]    public DateTime StartDate;     [DataMember]    [GreaterEqualTo(CompareAgainst.FieldOrProperty, "StartDate")]    public DateTime EndDate;     public TestClass(DateTime startDate, DateTime endDate)    {        StartDate = startDate;        EndDate = endDate;    }}   Service Contract Sample: [ServiceContract, ConstraintsValidatorBehavior]interface ITestConstraints{     [OperationContract]    [return:GreaterEqualTo(0)]     int MethodA(        [Between(0,100)]         int a,         [LessEqualTo(20)]         double b,         [NotEmpty]         string c);      [OperationContract]    int MethodB(        [Between(0, 100)]         int a,         [LessEqualTo(20)]         ref double b,         [NotEmpty]         out string c);     [OperationContract]    [return:LaterThanNow]    DateTime MethodC(        [GreaterThan(0)]         int a);       [OperationContract]    void MethodD(        [VerifyObject]         TestClass a);} Download at wcf.netfx3.com