Wednesday 20 February 2013

Url.Content ASP.NET equivalent

I keep needing this so thought I would put is somewhere:

in MVC you are given a very nice Url.Content element which allows you to build a site to the url with a tilde ~.

There is an equivalent in ASP.NET: Page ResolveUrl()

Friday 25 January 2013

MVC4 StrucutureMap ControllerFactory

I am not sure if this is new to MVC4 only, but it does appear that Dependency Injection with MVC just got easier. This code is borrowed, and referenced here so I don't have to keep going off and finding it.

First off I create a ControllerFactory for StrucutureMap

public class StructureMapControllerFactory : DefaultControllerFactory
{
    public IContainer Container { getset; }
    public StructureMapControllerFactory()
    {
        Container = ObjectFactory.Container;
    }
 
    protected override IController GetControllerInstance(System.Web.Routing.RequestContext requestContext, Type controllerType)
    {
        IController controller;
        if (controllerType == null)
        {
            throw new HttpException(404, String.Format(Resources.ControllerNotFound, requestContext.HttpContext.Request.Path));
        }
        if (!typeof(IController).IsAssignableFrom((controllerType)))
        {
            throw new ArgumentException(string.Format(Resources.NotAController, controllerType.Name),"controllerType");
        }
        try
        {
            controller = Container.GetInstance(controllerType) as Controller;
        }
        catch (Exception ex)
        {                
            throw new InvalidOperationException(string.Format(Resources.UnableToResolveController, controllerType.Name),ex);
        }
        return controller;
    }
}

Then in the Global.asax Application_Start method.
Add the setup for StructureMap, I tend to do all that in a separate class:
DependencyInjection.StructureMap.Initialise();
And then set the ControllerFactory to your new custom factory:
ControllerBuilder.Current.SetControllerFactory(new StructureMapControllerFactory());

Monday 17 December 2012

Split String from SQL Database

Sometimes you have to store information in one field.

This script is a scalar function, that will allow you to Split and return an index value, it even handles if there is no value split to return:

CREATE function [dbo].[SplitString](
 @String nvarchar (max),
 @Delimiter nvarchar (10),
 @position int
 )
RETURNS varchar(max) 
AS
begin
 declare @NextString nvarchar(max)
 declare @Pos int
 declare @NextPos int
 declare @CommaCheck nvarchar(1)
 declare @count int
declare @ValueTable table (ID int, Value varchar(max))
 --Initialize
 set @NextString = ''
 set @CommaCheck = right(@String,1) 
set @count = 0
 --Check for trailing Comma, if not exists, INSERT
 --if (@CommaCheck <> @Delimiter )
 set @String = @String + @Delimiter
 --Get position of first Comma
 set @Pos = charindex(@Delimiter,@String)
 set @NextPos = 1
 --Loop while there is still a comma in the String of levels
 while (@pos <>  0)  
 begin
  set @NextString = substring(@String,1,@Pos - 1)
  insert into @ValueTable ( [ID], [Value]) Values (@count, @NextString)
  set @count = @count + 1
  set @String = substring(@String,@pos +1,len(@String))
  
  set @NextPos = @Pos
  set @pos  = charindex(@Delimiter,@String)
 end
declare @val varchar(255)
select @val = value from @ValueTable where ID = @position
 return @val
end

Thursday 15 November 2012

Sort on Table Columns

Cannot remember if I found this or wrote it or a mix of the 2. I know it uses the JQuery UI Widget tempate so you will need to make sure to include that.


/*
* jQuery UI Progressbar @VERSION
*
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license
*
* http://docs.jquery.com/UI/Progressbar
*
* Depends:
*   jquery.ui.core.js
*   jquery.ui.widget.js
*/
(function ($, undefined) {
 
    $.widget("ui.columnsort", {
        version: "@VERSION",
        options: {
 
        },
 
        _create: function () {
            var self = this.element;
            $(self).addClass("sortTable").find("tr:first").addClass("sortColumns").children().addClass("sortColumn")
            .disableSelection().css("cursor""pointer").click(this._sortByColumn);
        },
        _sortByColumn: function () {
            var sortCell = $(this).closest(".sortColumn");
            var selectedIndex = sortCell.index();
            var hadclass = $(sortCell).hasClass("asc");
            $(sortCell).closest(".sortColumns").find(".sortColumn").removeClass("asc").removeClass("desc");
            hadclass ? $(sortCell).addClass("desc") : $(sortCell).addClass("asc");
            var table = $(this).closest("table");
            var rows = $(table).find("tr:not(.sortColumns)");
            rows.sort(function (a, b) {
                var keyA = $('td:eq(' + selectedIndex + ')', a).text();
                var keyB = $('td:eq(' + selectedIndex + ')', b).text();
                var checkkeyA = parseInt(keyA);
                var checkkeyB = parseInt(keyB);
                if (!parseInt(keyA)) {
                    checkkeyA = keyA;
                    checkkeyB = keyB;
                }
                if ($(sortCell).hasClass('asc')) {
                    return (checkkeyA > checkkeyB) ? 1 : -1;
                }
                else {
                    return (checkkeyA < checkkeyB) ? 1 : -1;
                }
            });
 
            rows.each(function (index, row) {
                if ($(row).hasClass("resultstableitema") || $(row).hasClass("resultstableitemb")) {
                    $(row).removeClass("resultstableitema").removeClass("resultstableitemb");
                    if (index % 2) {
                        $(row).addClass("resultstableitemb");
                    }
                    else {
                        $(row).addClass("resultstableitema");
                    }
                }
                table.append(row);
            });
        },
        _destroy: function () {
            this.element
   .removeCss("cursor");
        }
    });
})(jQuery);

Thursday 8 November 2012

Custom extensions that I use regularly


This is just a list of extensions that I use.

public static Guid ToGuid(this string stringValue)
        {
            try
            {
                return new Guid(stringValue);
            }
            catch (FormatException ex)
            {
                throw new FormatException("string could not convert to Guid");
            }
            catch (ArgumentNullException ex)
            {

                return Guid.Empty;
            }
        }

        public static int ToInt32(this string stringValue)
        {
            if (string.IsNullOrEmpty(stringValue))
            {
                return -0;
            }
            else
            {
                return Convert.ToInt32(stringValue);
            }
        }

        public static bool ToBoolean(this string stringValue)
        {
            if (string.IsNullOrEmpty(stringValue))
            {
                return false;
            }
            else
            {
                return Convert.ToBoolean(stringValue.ToInt32());
            }
        }

// dont really use this one, cannot guarentee that the lastname wasnt supposed to start with a lowercase
        public static string ToProperCase(this string stringValue)
        {
            if (string.IsNullOrEmpty(stringValue))
            {
                return string.Empty;
            }
            else
            {
                var ti = System.Threading.Thread.CurrentThread.CurrentCulture.TextInfo;
                return ti.ToTitleCase(stringValue.ToLower());
            }
        }

        public static bool IsNull(this object o)
        {
            return o == null;
        }

        public static bool IsNotNull(this object o)
        {
            return !o.IsNull();
        }

        public static bool IsNullOrEmpty(this string s)
        {
            return string.IsNullOrEmpty(s);
        }

        public static bool IsNotNullOrEmpty(this string s)
        {
            return !string.IsNullOrEmpty(s);
        }

        public static string ToValidFileName(this string value)
        {
            return Regex.Replace(Regex.Replace(value, @"\W", "_"), "_{2,}", "_");
        }

// this is a fun one, passing in a list of type T will generate a typed dataset
        public static DataSet ToDataSet<T>(this IList<T> value)
        {
            if (value != null && value.Count > 0)
            {
                var type = typeof(T);
                var properties = type.GetProperties();
                ConstructorInfo ci = type.GetConstructor(new Type[] { });
                T item = (T)ci.Invoke(new object[] { });
                var ds = new DataSet();
                var dt = new DataTable();
                foreach (PropertyInfo property in properties)
                {
                    var row = value.FirstOrDefault();
                    var dc = new DataColumn()
                    {
                        Caption = property.Name,
                        ColumnName = property.Name
                    };
                    if (row.IsNotNull())
                    {
                        var itemValue = property.GetValue(row, null);
                        if (itemValue.IsNotNull())
                        {
                            dc.DataType = itemValue.GetType();
                        }
                    }
                    dt.Columns.Add(dc);
                }
                foreach (T listItem in value)
                {
                    var dr = dt.NewRow();
                    foreach (var property in properties)
                    {
                        var listItemValue = property.GetValue(listItem, null);
                        if(listItemValue != null)
                        {
                            dr[property.Name] = property.GetValue(listItem, null);
                        }
                    }
                    dt.Rows.Add(dr);
                }
                ds.Tables.Add(dt);
                return ds;
            }
            else
            {
                return new DataSet();
            }
        }

Tuesday 30 October 2012

Custom CMS using HTTPHandlerFactory




This is a handy chunk of code I want to keep, it allows for the use of the HttpHandlerfactory to return pages that are content managed alongside physical pages.

namespace Web.Helpers {
public class HttpCMSHandlerFactory : IHttpHandlerFactory
{
public IHttpHandler GetHandler(HttpContext context, string requestType, string url, string pathTranslated)
{
    string pageName = Path.GetFileNameWithoutExtension(context.Request.PhysicalPath);
    
    //on Server.Transfer the context is kept, so this just overrides the existing value.
    if (context.Items.Contains("PageName")) 
    {
        context.Items["PageName"] = pageName; } else { context.Items.Add("PageName", pageName); }
        FileInfo fi = new FileInfo(context.Request.MapPath(context.Request.CurrentExecutionFilePath)); 

        //if File is not physical 
        if (fi.Exists == false) 
        {
             //Check if is survey
             if (pageName.IndexOf("Survey", 0, StringComparison.InvariantCultureIgnoreCase) &gt;= 0) 
            { return PageParser.GetCompiledPageInstance(url, context.Server.MapPath("~/Survey.aspx"), context); 
            } 
            else 
           {
            //return page to CMS handler the context containing "PageName" is passed on to this page, which then calls to the database to return the copy.
                return PageParser.GetCompiledPageInstance(url, context.Server.MapPath("~/CMSPage.aspx"),  context); 
            } 
        } 
        else 
        {
            // Returns real page.
            return PageParser.GetCompiledPageInstance(context.Request.CurrentExecutionFilePath, fi.FullName, context); 
        } 
    }
}

All that is then needed is to override the *.aspx handler on the iis site config (which should already be there for an asp.net sites) and also add the following to the web.config:
<httphandlers>
<add path="*.aspx" type="Web.Helpers.HttpCMSHandlerFactory, Web.helpers" verb="*"/>
</httphandlers>

Friday 26 October 2012

When Session times out before FormsAuthentication is dropped

Just wanted to keep this safe, there are probably better ways of doing this, but I often find that the FormsAuthentication object holds on to your login, after the session has cleared.

This often happens when I am testing a site and making changes, the site will drop it's session but the FormsAuthentication stays populated and logged in causing an error to be thrown until you logout and back into to repopulate the necessary session objects.

So in the OnInit event I add a simple check:
    protected override void OnInit(EventArgs e)
    {
        base.OnInit(e);
        var current = Path.GetFileNameWithoutExtension(Request.PhysicalPath);
        if (current.StartsWith("Registration", StringComparison.InvariantCultureIgnoreCase) && Session["Objectx"] == null)
        {
            Response.Redirect("SignIn.aspx");
        }
    }

The above only worries about pages with the word Registration in then page name.

For an entire site you need to be a bit different:
    protected override void OnInit(EventArgs e)
    {
        base.OnInit(e);
        var current = Path.GetFileNameWithoutExtension(Request.PhysicalPath);
        if (!current.Equals("SignIn", StringComparison.InvariantCultureIgnoreCase) && Session["Objectx"] == null)
        {
            Response.Redirect("SignIn.aspx");
        }
    }