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");
        }
    }


Wednesday, 3 August 2011

OptGroup with asp:Dropdownlist

Most are aware that the out of the box DropdownList that comes with asp.NET doesnt allow for OptGroups. These are quite handy when it comes to structuring the layout.

One way around this is to use jQuery to insert the items required to make optgroup work.

Define your asp:DropdownList, remember to set the cssclass attribute as this makes it easier to find.

In this case I had a dropdown with the css class of eventDropDown attached.

In the data returned to the Dropdown I make sure 2 extra rows are added to separate the 2 sets of options, in this case one is PE and one is OE.

initially the data is bound with the separators (slightly edited)
<select>
<option>PE</option>
<option>ONE</option>
<option>OE</option>
<option>TWO</option>
</select>

using the :contains selector that comes with the standard jQuery libraray I was able to find the option of PE and OE to be replaced with my optgroup choices.
I have made the assumption that if PE exists, then so does OE. Makes life a bit easier.

<script type="text/ecmascript">
var item = $('.eventDropDown option:contains("PE")');
if (item != null) {
item.replaceWith("<optGroup label='Preferred Events' />");
item = $('.eventDropDown option:contains("OE")');
item.replaceWith("<optGroup label='Other Events' />");
}
</script>

I'm not sure on the accessibility level of what I am doing, but visually this will work for most cases where you want this to happen.

If you do want proper option groups do your site in MVC and make your own custom control, its fun. this is a way out for a control in ASP.NET.

Friday, 15 July 2011

Using LinQ on a DataSet

This is quite straightforward:

Apply the AsEnumerable() extension to your DataTable, allowing you to select the data you want and return it as a collection. By using the extension AsDataView(), the collection is then returned as a friendly DataView object:

for example:
var dv = (from dr in ds.Tables[0].AsEnumerable()
where dr[0] == x
select dr).AsDataView();


Tuesday, 31 May 2011

Grouping with LinQ

Using LinQ to group a set of data by something is quite straightforward.

In the example below I am returning a list of bookings, which is very flat. I wanted to group the data returned by the BookingID

Using group on BookingID, I am able to rearrange the data to "group" sets of data that relate to a specific booking. Brilliant!

var bkgs = dal.GetBookings();

var distinctbkgs = (from x in bkgs
group x by x.BookingID into xx
select new
{
Booking = xx.First(),
RelatedBookings = xx.ToList()
}).ToList();

Monday, 7 March 2011

left join with LinQ comprehension syntax

I was trying to find a way to perform a left join on 2 comparable sets of data using LinQ, but the join keyword only appears to perform an inner join (unless I missed something).

By performing a LinQ statement for the Del entry at the point I create the anonymous type, the following output would act like a left join (returning a null for the Del value when there is no match).

I then go on to select all the null entries using the extension methods and call a delete routine for each entry found.

(from x in Entries
where x.Information["Information3"] == Session["GINumber"].ToString()
select new
{
Pre = x,
Del = (from y in _delegates
where y.EmailAddress == x.Information["Information1"]
select y.EmailAddress).SingleOrDefault()
}).Where(x => x.Del == null).ToList().ForEach(x => Service.DeleteEntry(x.Pre.InformationID));


As an aside I found out that the term for the “from” “in” style of LinQ is called “Query Comprehension Syntax”.

Tuesday, 8 February 2011

Disable asp.net button

adding the following in the page load event in your ASP.NET page. This will setup the ability to disable the button you click, until the submission is complete or an error occurs.

MyButton.Attributes.Add("onclick", "this.disabled=true;" + Page.ClientScript.GetPostBackEventReference(MyButton, "").ToString());

Monday, 17 January 2011

Split String To Dictionary

I have created a Survey System, which allows an admin to set the questions.

One question type is a dropdownlist and the information needed (to keep it simple) was stored as a semi-colon separated list (I also extended this to allow colon separated values within that to allow key and value sets).

for example:
spring;summer;autumn;winter
or
0:spring;1:summer;2:autumn;3:winter

Both are valid and the second example will store the values defined as the answer.

I wanted to split a string into a Dictionary and set a return for use on an MVC SelectList,

I refactored out the SplitAndReturnIndex to handle case where the string does not contain a Key, only a value, as can be seen from the code:


public IDictionary QuestionValues()
{
return Question.SurveyItemValues.Split(';')
.Select(x => new { Key = SplitAndReturnIndex(x, 0), Value = SplitAndReturnIndex(x, 1) })
.ToDictionary(x => x.Key, x => x.Value);
}

private string SplitAndReturnIndex(string x, int indexValue)
{
return x.IndexOf(':') == -1 ? x : x.Split(':')[indexValue];
}

Tuesday, 4 January 2011

Hash Password using HMACSHA1 or HMACSHA512

Quite a handy snippet to generate an HMACSHA1 encoded string, I use this for passwords, but it could be used generate a check sum when passing values through to a webservice.

public static string GeneratePassword(string valueToHash)
{
byte[] saltValueBytes = Encoding.ASCII.GetBytes("This is for the Salt");
// Change passkey value to known value, I tend to use a guid
Rfc2898DeriveBytes passwordKey = new Rfc2898DeriveBytes("96D9E8D3-1318-4291-B459-84EAB0E268A6", saltValueBytes);
byte[] secretKey = passwordKey.GetBytes(16);
HMACSHA1 myHash = new HMACSHA1(secretKey);
byte[] encodedValue = Encoding.UTF8.GetBytes(valueToHash);

return Convert.ToBase64String(myHash.ComputeHash(encodedValue));
}


The problem with this, has always been everyone has the same salt.

So a change in security and use of SHA512:

With a way to generate a unique Salt:


public byte[] GenerateSalt()
        {
            System.Security.Cryptography.RNGCryptoServiceProvider r = new System.Security.Cryptography.RNGCryptoServiceProvider();

            byte[] array = new byte[16];

            r.GetBytes(array);

            return array;
        }

And return the Hash value with Generated Salt Passed in:

        public string GetHash(string password, byte[] salt)
        {
            string ret = string.Empty;

            try
            {
                byte[] passwordBytes = Encoding.ASCII.GetBytes(password);

                byte[] input = new byte[salt.Length + passwordBytes.Length];

                salt.CopyTo(input, 0);

                passwordBytes.CopyTo(input, salt.Length);

                System.Security.Cryptography.SHA512CryptoServiceProvider cr = new System.Security.Cryptography.SHA512CryptoServiceProvider();

                ret = Convert.ToBase64String(cr.ComputeHash(input));
            }
            catch (Exception Ex)
            {
                throw new Exception("Error hashing password", Ex);
            }

            return ret;
        }

Remember to save the salt somewhere that can be referrenced with the encrypted value, so you can check it.

Tuesday, 21 December 2010

JQuery Vertical Scroller

useful chunk of code for scrolling a list of something, vertically using JQuery

an example of the list html

<ul id="list">
<li>One</li>
<li>Two</li>
<li>Three</li>
<li>Four</li>
</ul>

this is the jquery

<script type="text/ecmascript">
var list = $("#list");
list.addClass("scrolllist");
list.wrap("<div class=\"clipper_container vert\"></div>").wrap("<div class=\"clipper\"></div>");
var clip = list.parent();
var container = clip.parent();
var items = list.children();
var targetHeight = 0;
items.each(function () { targetHeight += $(this).height() });
var cumulativeHeight = 0;
items.each(function () { cumulativeHeight += $(this).height() });
while (cumulativeHeight < targetHeight * 3) {
items.clone().appendTo(list);
items = list.children();
cumulativeHeight = 0;
items.each(function () { cumulativeHeight += $(this).height() });
}
list.css({ "height": cumulativeHeight + "px" });
var interval = setInterval(function () {
if (clip[0].scrollTop == targetHeight) {
clip[0].scrollTop = 1;
}
else {
clip[0].scrollTop += 1;
}
}, 10);
</script>

and the css

/* css for Scrolling element */

.clipper_container
{
position: relative;
}
.clipper
{
position: relative;
overflow: hidden;
z-index: 2;
height: 493px;
width:144px;
}


.scrolllist
{
position: absolute;
top: 0;
left: 0;
z-index: 1;
overflow: hidden;
margin: 0;
padding: 0;
list-style: none;
height: 493px;
width: 150px;
margin: 0px;
padding: 0px;
}


.scrolllist li
{
list-style-type: none;
padding: 0px;
margin: 0px;
text-align:center;
}

.vert
{
/* wider than clip to position buttons to side */
width: 150px;
height: 493px;
margin-bottom: 1.5em;
}

.clipmain, .scolllistmain, .vertmain
{
height:600px;
}


An additional Development I have made for the scroller is to have a stepped scroll using animate.

To do this simply replace the interval variable stated above with the following
var interval = setInterval(
function () {
var target = targetHeight + list.position().top;
if(target == -50)
{
list.css({top:-50});
}
list.animate({ top: '-=50' }, "fast");
}, 1000);

Friday, 17 December 2010

MVC 3 Razor Views and Site Areas

Been working quite a lot over the last few years with MVC and since the release of Razor with MVC3 I have been quite giddy.

The fluid transition you can now have between HTML and programmatic code, has made the all cshtml files a thing of beauty.

There are still some bits I am getting to grips with; the "Areas" functionality now provided for example.

In one case I am creating a mobile site, so creating a new area allows me to create a new _layout.cshtml file to reference a new css file and I found that you can reused any controllers from your parent MVC site, by adding the namespace to the namespaces array in the MapRoute object saving me a lot of work.


public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"ms_default",
"ms/{controller}/{action}/{id}",
new {controller="Home", action = "Index", id = UrlParameter.Optional },
// this defines the namespace for the controllers I have already created in the parent site.
new string[] {"TMS.WEB.Controllers"}
);
}

Then I needed to add all the views from the parent site I wanted. I had to drop in the views even though they are the same for now, as it kept going off to use the layout and views defined in the parent site.

It would have been useful to only have to define as few files as necessary, but I guess I can just copy and replace the files as I maintain the site.

Help with Linked Servers using SQL Scripts

Cannot remember why I needed to do this, think something was being funny when trying to run the Enterprise Manager as a local account rather than a domain account;


EXEC master.dbo.sp_addlinkedserver
@server = 'your linked server name',
@srvproduct = '',
@provider = 'MSDASQL',
@provstr = 'DRIVER={SQL Server};SERVER=MyServer;UID=sa;PWD=sapwd;'


The above creates a default link to the Master Database on your desired server. Once Created go into the properties of the linked server and fill in the "Catalog" field to point to the database you want. 2

Similar sort of Cursor, but slightly different

Got fed up of modifying the previous cursor to do this simpler event.

Basically finds every table in a database and then returns the first row, prefixing the information returned for each table with the tablename.

Saves time running a select statement for each table and useful for finding a table that you know must exist, but isnt clearly named on the database.


declare @command varchar(255)
declare @tablename sysname
declare @count int
DECLARE StatusCursor CURSOR FOR

select a.name from sysobjects a where a.type ='U' order by a.name

Open StatusCursor
Fetch next from StatusCursor into @tablename
WHILE @@FETCH_STATUS = 0
BEGIN
exec ('select top 1 ' + '''' + @tablename + ''', * from ' + @tablename + '')
Fetch next from StatusCursor into @tablename
END
CLOSE StatusCursor
Deallocate StatusCursor

Cursor code for table objects

I had done something cross databases before using sysdatabases, but this time I needed to search for specific text in any column on an table in a known database.



declare @command varchar(255)
declare @tablename sysname
declare @columnname sysname
declare @count int
DECLARE StatusCursor CURSOR FOR

select a.name,b.name from sysobjects a join syscolumns b on a.id = b.id where a.type ='U' order by a.name

Open StatusCursor
Fetch next from StatusCursor into @tablename, @columnname
WHILE @@FETCH_STATUS = 0
BEGIN
if(@columnname = 'FOO1')
begin
print @tablename
end
Fetch next from StatusCursor into @tablename, @columnname
END
CLOSE StatusCursor
Deallocate StatusCursor

Find the index of a list item

It took me a while to find how to do this, but once I had, my eyes will be ever open to the beauty of Linq.

The following code was used in a problem I was working on from Programming Praxis and compares a specific charater to a list of strings

//where row is a List variable and char1 is a charater of interest
var row1 = rows.FindIndex(r => r.Contains(char1) == true)

In the problem above the character can only appear once in the collection.