Monthly Archives: October 2006 - Page 2

Redirecting based on a role in the loggedin event of the login control

Today I had to fix a website that is built by the guys over in Russia. Completely asp.net no castle involved whatsoever. There is not even an O/R mapper in the application.

Real basic stuff. Sql datasource gridview/formview type of things.

The client asked me to do redirect their site to certain pages depending on which role the user is in.

Cool. Let’s handle the LoggedIn event of the Login control. This is what I started of with. Makes perfect sense to me that that should work.

    protected void Login1_LoggedIn(object sender, EventArgs e)

    {

        if (Roles.IsUserInRole(“School”))

            Response.Redirect(string.Format(“~/Career/School.aspx?ID={0}”, CareerUser.GetUserTypeId(Membership.GetUser().ProviderUserKey)));

        if (Roles.IsUserInRole(“Student”))

            Response.Redirect(string.Format(“~/Career/Student.aspx?ID={0}”, CareerUser.GetUserTypeId(Membership.GetUser().ProviderUserKey)));

        else

            Response.Redirect(“~/Login.aspx”);

    }

Now as expected that didn’t do the trick. But this does

    protected void Login1_LoggedIn(object sender, EventArgs e)

    {

        /*I have to do it this way because there is no cookie set yet so Membership.GetUser() returns an empty object.

        * The same goes for the roles. No cookie means no data for the standard function.

        */

        Login login = sender as Login;

        Guid userObjectKey = (Guid)Membership.GetUser(login.UserName).ProviderUserKey;

        Guid userId = CareerUser.GetUserTypeId(login.UserName, userObjectKey);

        if (Roles.IsUserInRole(login.UserName, “School”))

            Response.Redirect(string.Format(“~/Career/School.aspx?ID={0}”, userId));

        if (Roles.IsUserInRole(login.UserName, “Student”))

            Response.Redirect(string.Format(“~/Career/Student.aspx?ID={0}”, userId));

        else

            Response.Redirect(“~/Login.aspx”);

    }

Just thought I’d share this for other people that have this problem.

Anyway this is wtf numero 10 today. And I haven’t had these moments in the last couple of weeks, using castle and all, so I was feeling a little nostalgic about the whole thing.

Some news on nblogr

NBlogr isn’t dead.. It just underwent a transformation for the better.

I also changed the title of the application from NBlogr – An atlas blogging engine to NBlogr – a blogging engine built on simplicity
The reason for this change is the fact that it is currently built using jquery as javascript library.  I will look at atlas again when it releases.

I moved NBlogr to run on castle.  During the course of the next week I’ll complete my posts on how to do Castle development with base4

If you’re interested in how it looks or you want a preview the last source in the repository builds and you should be able to run it in the development server of visual studio

I had a chat with JD a while ago and he asked me about plugins. At that time I knew already I wanted to provide something for users to be able to add plugin’s to the database.  But I hadn’t really given it much thought on how I would do that.

My reasoning on this subject is :
I want users to be able to add a plug in at runtime. Plugin’s for a blog are lately both server related client side. So I will create a plugin factory with a couple of providers like a google video provider, grouper video, flickr, bookmark services.  And you can write a plugin using javascript and ironpython code. The engine will evaluate that code at runtime and there has been no application restarting etc. If somebody has a better plan for doing a plugin infrastructure please let me know I haven’t done any of the ground work for this yet but create a schema in base4 so now would be the best time to stop me from making big mistakes.

Another improvement is the fact that when nblogr reaches release it will come with a couple of templates for you to chose from. I’ll try to include one that is built on the css scheme of csszengarden that way you’ll have an infinite repository of css to make your blog look differently instantaneously.

The next improvement is that a user is now able to mimic wildcard requests and nblogr will handle those. So there is no need for appending aspx to pages for rewriting (routing it is called in monorail)  You get the choice in the config file to have your webserver handle the wild card mapping or nblogr. When you choose for nblogr nblogr will need write access to 2 folders in your website and create a shadow folder structure to represent the rewrite tree structure. There is weaker point here and that is that the first default document in IIS must be set to Default.aspx If you can map an extension to aspnet_isapi.dll at your webserver then you can also have the urls rewritten using a branded extension.

I think that this are the 3 major changes for the moment to the engine.  This did set me back for the next release with a couple of weeks but in the end the final release can be done much more quickly than it would have been possible using the code I had before.

I also promise that this time things mostly stay as they are. There will be no more experimenting but just getting Nblogr to a proper release state and shipped.

Hosting Base4 inside your web application

Following up on the post of yesterday.  To use base4 with asp.net often you do not have the possibility to host base4 as a windows service. But to host base4 in the same appdomain as you website isn’t all that hard.

I’ll just share my code and how to use it. The way to go is to create a class that extends the HttpApplicatin and handle the application start and end events.

I’ll also post the code i have to integrate this with castle.

This is my base HttpApplication, every web app inherits of this one.

using System;

using System.Collections.Generic;

using System.Text;

using System.Web;

using Base4.Storage.Server;

using System.Text.RegularExpressions;

using System.Reflection;

using System.Data.SqlClient;

using System.Configuration;

using Base4.Storage;

using System.Xml;

using System.IO;

 

namespace Flanders.Library.Base4Integration

{

    public class Base4HttpApplication : HttpApplication

    {

        ServerConfiguration config;

        IServerProxy proxy;

 

 

        public Base4HttpApplication()

        {

 

        }

 

        public virtual void Application_Start(object sender, EventArgs e)

        {

            //Build the base4 server configuration from the connection strings settings in the web.config

            config = new ServerConfiguration();

            config.Store.Root = Server.MapPath(“~/”);

            config.Store.Root = config.Store.Root.EndsWith(“\\”) ? config.Store.Root

                + “App_Data\\Base4″ : config.Store.Root + “\\App_Data\\Base4″;

 

            //Set the application name of the store. In my case I define a title for my application in a

            //solution info file and use that as my app name

            //For this to work you will need to name your database the same as your applicationname

            if (Application["AppName"] == null)

            {

                Assembly assembly = Assembly.GetCallingAssembly();

                Application["AppName"] =

                    (AssemblyTitleAttribute.GetCustomAttribute(assembly, typeof(AssemblyTitleAttribute)) as AssemblyTitleAttribute).Title;

            }

 

            config.Store.Name = Application["AppName"].ToString();

            config.Store.Provider = “SQL2005″;

 

            //Set the port for base4 to listen on.  This is defined in the web.config app settings

            if (Application["AppPort"] == null)

                Application["AppPort"] = string.IsNullOrEmpty(ConfigurationManager.AppSettings["Base4.Port"]) ? 8809 :

                    int.Parse(ConfigurationManager.AppSettings["Base4.Port"]);

 

            config.Store.Port = (int)Application["AppPort"];

            //We are hosting base4 in the same process as the website. so localhost will do :)

            config.Store.MachineName = “localhost”;

 

            //Set the connection string for the base4 store

            string connectionStringName = ConfigurationManager.AppSettings["DefaultConnection"];

            if (string.IsNullOrEmpty(connectionStringName) && ConfigurationManager.ConnectionStrings != null

                && ConfigurationManager.ConnectionStrings.Count > 0)

                connectionStringName = ConfigurationManager.ConnectionStrings[0].Name;           

 

            config.Store.ConnectionString = string.IsNullOrEmpty(connectionStringName) ?

                ConfigurationManager.AppSettings["Store.ConnectionString"] :

                ConfigurationManager.ConnectionStrings[connectionStringName].ConnectionString;

 

            //Set the master connection string

            SqlConnectionStringBuilder connStrBuilder = new SqlConnectionStringBuilder(config.Store.ConnectionString);

 

            connStrBuilder.InitialCatalog = “master”;

            config.MasterConnectionString = connStrBuilder.ToString();

 

            //Check if we have a directory to store the files generated by base4

            if(!Directory.Exists(config.Store.Root))

                Directory.CreateDirectory(config.Store.Root);

 

            //Actually start the server

            proxy = ServerFactory.StartServer(config, false);

 

            //Set the context for base4

            string base4Context = string.Format(“tcp://Server:@localhost:{0}/{1}”, Application["AppPort"], Application["AppName"]);

 

            Application["Base4Context"] = base4Context;

 

            //Set the default storage context for base4

            StorageContext.SetDefault(base4Context);

 

        }

 

        public virtual void Application_End(object sender, EventArgs e)

        {

            proxy.Stop();

        }

 

    }

}

Now to integrate this with monorail then this is you application class in your website :

 

using System.Web;

using Castle.Windsor;

using Base4.Storage;

using System.Configuration;

using Flanders.Library.Base4Integration;

 

namespace NBlogr.Presentation

{

    public class ASPGlobal : Base4HttpApplication, IContainerAccessor

    {

        private static MonoRailContainer container;

 

        public override void Application_Start(object sender, System.EventArgs e)

        {

            base.Application_Start(sender, e);

            container = new MonoRailContainer();

        }

 

        public override void Application_End(object sender, System.EventArgs e)

        {

            container.Dispose();

            base.Application_End(sender, e);

        }

 

 

        #region IContainerAccessor Members

 

        public IWindsorContainer Container

        {

            get { return container; }

        }

 

        #endregion

    }

}

The global.asax should only contain one line :

<%@ Application Inherits="NBlogr.Presentation.ASPGlobal" Language="C#" %>

Base4 and NLog

As you know already I like base4 a lot

Alex Henderson has got a nice post on integrating base4 much prettier than I did in castle.  Later on today I’ll post what I made of it

I tried to use log4net but didn’t succeed.  So I switched to nlog which I like a lot.

Now to integrate nlog with base4 wasn’t all that hard.

This is the type from my schema which just stores about anything i would want to know about a particular event. and probably more in my case :)

 

    <Type FullName=NBlogr.Core.AppEvent baseName=Base4.Storage.ItemImpl keyProperty=Id version=1 mode=Rich>

      <Property name=ApplicationContext typeName=Base4.Storage.ContentStream nullable=True />

      <Property name=EventTime typeName=System.DateTime />

      <Property name=Exception typeName=System.String nullable=True length=1025 />

      <Property name=Id typeName=System.Guid unique=True />

      <Property name=Level typeName=System.String length=256 />

      <Property name=LoggerName typeName=System.String length=256 />

      <Property name=Message typeName=System.String length=1025 />

      <Property name=Sequence typeName=System.Int32 nullable=True />

      <Property name=StackTrace typeName=System.String nullable=True length=1025 />

      <Property name=UserStackFrame typeName=System.String nullable=True length=1025 />

    Type>

 

The actual target :

 

namespace NBlogr.Common.Base4Integration

{

    ///

    /// This is a target for the nlog logging library.

    /// This is dependent on the NBlogr.Core.xml file and Base4.

    ///

    [Target("Base4Target")]

    public class Base4Target : TargetWithLayout

    {

        private string _host = “tcp://server:@localhost:999/Base4_Default”;

 

        public string Base4Context

        {

            get { return _host; }

            set { _host = value; }

        }

 

        protected override void Write(LogEventInfo logEvent)

        {

            string logMessage = CompiledLayout.GetFormattedMessage(logEvent);

 

            if(StorageContext.Default == null)

                StorageContext.SetDefault(Base4Context);

 

            AppEvent appEvent = new AppEvent();

            appEvent.Sequence = logEvent.SequenceID;

 

            if(logEvent.Context != null && logEvent.Context.Count > 0)

                appEvent.ApplicationContext.Content = GetZippedBytes(logEvent.Context);

 

            appEvent.EventTime = logEvent.TimeStamp;

 

            if(logEvent.Exception != null) appEvent.Exception = logEvent.Exception.ToString();

 

            if(logEvent.StackTrace != null) appEvent.StackTrace = logEvent.StackTrace.ToString();

            if (logEvent.UserStackFrame != null) appEvent.UserStackFrame = logEvent.UserStackFrame.ToString();

 

            appEvent.Level = logEvent.Level.Name;

            appEvent.LoggerName = logEvent.LoggerName;

            appEvent.Message = logMessage;

 

            appEvent.Save();

 

 

        }

 

        private byte[] GetZippedBytes(IDictionary evt)

        {

            MemoryStream ms = new MemoryStream();

 

            BinaryFormatter formatter = new BinaryFormatter();

 

            formatter.Serialize(ms, evt);

 

            GZipStream zipStream = new GZipStream(ms, CompressionMode.Compress);

 

            BinaryReader bRdr = new BinaryReader(zipStream);

 

            return bRdr.ReadBytes((int)zipStream.Length);

 

        }

    }

}

JQuery Greybox revisited

I’ve been using the jquery library in conjunction with castle lately. And to display sub content of a page i need something to show the page in. Like a modal dialog box :)

I found the greybox plugin but it wasn’t quite what I was looking for. So I added a couple of features to it.  The code is below. For the stylesheet etc I suggest you visit the original greybox script.

 /* Greybox Redux II
 * Written by : Ivan Porto Carrero
 * I changed the greybox code so that it would support ajax instead of an iframe.
 * You need the interface elements 
 * Required: http://jquery.com/
 * Written by: John Resig
 * Based on code by: 4mir Salihefendic (http://amix.dk)
 * License: LGPL (read more in LGPL.txt)
 */

var GB_DONE = false;
var GB_HEIGHT = 400;
var GB_WIDTH = 400;

function GB_show(caption, url, height, width, hideOnWindowClick) {
  GB_HEIGHT = height || 400;
  GB_WIDTH = width || 400;
  if(!GB_DONE) {
    $(document.body)
      .append("
" + "Close window
"
); $("#GB_window img").click(GB_hide); if(hideOnWindowClick) $("#GB_overlay").click(GB_hide); $(window).resize(GB_position); GB_DONE = true; } $('#GB_overlay').hide(); $('#GB_window').hide(); if(url) $('#GB_Content').load(url,null,function(request){helpers.initPage();}); GB_position(); if ($().OpenVertically != undefined) // are interface elements supported ? $("#GB_window").OpenVertically(500); else $("#GB_window").slideDown("slow"); $("#GB_caption").html(caption); $("#GB_overlay").show(); $('#GB_Content').show(); }; function GB_hide() { $('#GB_Content').html('').hide(); if($().CloseVertically != undefined) $('#GB_window').CloseVertically(500); else $('#GB_window').hide('slow'); setTimeout('$("#GB_overlay").hide();$("#GB_window").hide();',500); }; function GB_position() { var de = document.documentElement; var w = self.innerWidth || (de&&de.clientWidth) || document.body.clientWidth; $("#GB_window").css({width:GB_WIDTH+"px",height:GB_HEIGHT+"px", left: ((w - GB_WIDTH)/2)+"px" }); };
Page 2 of 212