Twitter Feed Popout byInfofru

Modifying Connection Properties of excel file

We need to modify about 100+ excel files which are connecting to data connections files sitting in d

We were in need to modify about 100+ excel files which are connecting to data connections files sitting in data connection library of SharePoint 2010. The property we needed to change is “Always user connection file” in connection properties as shown below. Of course programmatically.

image

First of, I added the reference of “Microsoft.Office.Interop.Excel” in project and include it in code, like below

using xls = Microsoft.Office.Interop.Excel;

Then, read excel file from physical location and changed its connection properties using the code below

var application = new xls.Application();
try
{       

var application = new xls.Application();   // Creating excel application object
try
{
     string readLocation = @"D:\Documents\myfile_1.xlsx";
     var workbook = application.Workbooks.Open(readLocation); // Open excel workbook

    foreach (xls.WorkbookConnection con in workbook.Connections) // Iterating all connections
     {

            // Check for other properties, if you have to. For me, I am dead sure that all files wouldn’t be using connection files
             con.OLEDBConnection.AlwaysUseConnectionFile = true;
     }

    workbook.Save(); // Saving back workbook
}
catch (Exception)
{
     throw;
}
finally
{

        // These clean up lines are important to run otherwise, you will end up having an orphan excel instance sitting idle.
         application.Workbooks.Close();
         application.Quit();
}

How to redirect to default login page from action

I have been using Authorize attribute heavily to manage user authorizations, but at times just Authorize attribute is not enough. For an instance, I want user to access the Edit page of any entity which he created. In other words I don’t want him to edit records created by other users.

We cannot do this using Authorize only because it is design to limit access to an action regardless of what data is being passed to it. Thus, in this case you can maintain CreatedUser field in the record table and check on the Action if the logged in user is authorize to do this edit. Here is the code for that.

 

if (myrecord.OwnerId != User.Identity.Name) {

return new HttpUnauthorizedResult();

}

 

You can return HttpStatusCodeResult(403) too but that will only display the default access denied page of IIS, which is not we want and this is where “HttpUnauthorizedResult” comes handy.

Ambiguous in the namespace problem

From the last few days, I was ignoring an error that keep coming at the compile time. I spent some two hours on it before but didn’t get it work. The error is quit confusing and of course difficult to manage.

'ApplicationSettingsBase' is ambiguous in the namespace 'System.Configuration'

'MailMessage' is ambiguous in the namespace 'System.Net.Mail'

And there are couple of other similar errors that is pointing to some ambiguous references in my project.  The confusing part is that the MailMessage object throws similar error when you are importing the old and new email namespace.

For example,

Imports System.Web.Mail
Imports System.Net.Mail

So if you are only encountering ambiguous problem in MailMessage object. It is more possible that you have define both the namespaces in your code behind which is actually confusing the compiler about your referencing object.

The quick solve for this problem is that remove Imports System.Web.Mail and it should work smooth. But with me, I never used the old asp.net mail namespace in my project.

Then I start looking at my references and luckily I found the problem there. Follow the steps below to investigate the issue

1. Go to your project

2. Then references

3. Right click on “System” and see properties. it should point to the following path

x:\Windows\Microsoft.NET\Framework\v2.0.50727\System.dll

Where x is name of your operating system directory. This was the problem with my project. I had my operating system install on “D” drive and some how it is pointing to “C” drive which is the root cause of this problem.

After that I verify all my references and found 5 –6 assemblies that are pointing to wrong path and get it worked.

Also note, the problem can occur in any type of project either it is website , web application etc.

Custom Paging in Grid view

So, it takes too long for me to write this post. even though I completed the coding stuff a week back but it is really hard to manage time these days.In this post, I will explain and demonstrate you how to create custom paging in Grid view control. Paging which works like the Google Paging. Let me elaborate more, say for example you have a record set of 500 items and you want to display 10 items per page. Now what happen to the pages numbers. Either you use the default with “..” sign after 10th page link which cause the post back and then get some new page numbers. Or you want to make it like Google. i.e as soon as user move forward on page index, hide the previous pages and show the new numbers and when user is getting back hide new numbers and show the previous page links. following image can give you some idea what we are going to do.gvpaging_scgvpaging_sc2To start, lets first create a Grid view .
   1: <asp:GridView ID="GridView1" runat="server" AllowPaging="True"
   2:     onrowcreated="GridView1_RowCreated" >
   3: </asp:GridView>
Yes, we have allow the paging but we are not going to use the default paging of asp.net. That is why we have write onrowcreated implementation in which we will simply detect and hide the pager row.
   1: protected void GridView1_RowCreated(object sender, GridViewRowEventArgs e)
   2:  {
   3:      if (e.Row.RowType == DataControlRowType.Pager)
   4:      {
   5:          e.Row.Visible = false;
   6:      }
   7:  }
Now lets move to some global variables which we need through out our code.
   1: const int pageSize = 10;
   2: const int pageDispCount = 10;
   3: private DataTable dt = new DataTable();
pagesSize : number of records we want to display per page.pageDispCount : number of page numbers we want to display on custom paging.dt : A datatable which we will use to store data and use it on different post backs.Ok, now we need to get data from database, dump it to datatable and define the datasource of grid view.
   1: protected void bindData()
   2: {
   3:     SqlConnection objSqlCon = new SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["AdventureWorksConnectionString"].ToString());
   4:     objSqlCon.Open();
   5:
   6:     SqlDataAdapter objSqlDa = new SqlDataAdapter("select * from Production.Product", objSqlCon);
   7:
   8:     objSqlDa.Fill(dt);
   9:
  10:     GridView1.DataSource = dt;
  11:     GridView1.DataBind();
  12:
  13:     managePaging(dt);
  14: }
On line number 13, managePaging function will be used later to implement the paging logic. But before that, lets understand that we have taken the datatable as a global variable and each time after postback when we try to read our datatable we will get no results because there is no state management for this object.So lets override the LoadViewState and SaveViewState function of System.Web.UI.Page to save and restore the datatable by using viewstate.
   1: protected override object SaveViewState()
   2: {
   3:   object baseState = base.SaveViewState();
   4:   return new object[] { baseState, dt };
   5: }
   6: protected override void LoadViewState(object savedState)
   7: {
   8:   object[] myState = (object[])savedState;
   9:   if (myState[0] != null)
  10:       base.LoadViewState(myState[0]);
  11:
  12:   if (myState[1] != null)
  13:   {
  14:       dt = (DataTable) myState[1];
  15:       GridView1.DataSource = dt;
  16:       GridView1.DataBind();
  17:
  18:       managePaging(dt);
  19:   }
  20:
  21:   }
Well, SaveViewState function is simply putting the base.SaveViewState object and datatable in and object and returning it. A Simple Logic :)Where as, LoadViewState is retrieving and type casting the object exactly in the sequence it was save in the SaveViewState method.
   1: protected void managePaging(DataTable _dt)
   2: {
   3:     if (_dt.Rows.Count > 0)
   4:     {
   5:
   6:         // Variable declaration
   7:         int numberOfPages;
   8:         int numberOfRecords = dt.Rows.Count;
   9:         int currentPage = (GridView1.PageIndex);
  10:         StringBuilder strSummary = new StringBuilder();
  11:
  12:
  13:         // If number of records is more then the page size (specified in global variable)
  14:         // Just to check either gridview have enough records to implement paging
  15:         if (numberOfRecords > pageSize)
  16:         {
  17:             // Calculating the total number of pages
  18:             numberOfPages = (int)Math.Ceiling((double)numberOfRecords / (double)pageSize);
  19:         }
  20:         else
  21:         {
  22:             numberOfPages = 1;
  23:         }
  24:
  25:
  26:         // Creating a small summary for records.
  27:         strSummary.Append("Displaying <b>");
  28:
  29:         // Creating X f X Records
  30:         int floor = (currentPage * pageSize) + 1;
  31:         strSummary.Append(floor.ToString());
  32:         strSummary.Append("</b>-<b>");
  33:         int ceil = ((currentPage * pageSize) + pageSize);
  34:
  35:         //let say you have 26 records and you specified 10 page size, 
  36:         // On the third page it will return 30 instead of 25 as that is based on pageSize
  37:         // So this check will see if the ceil value is increasing the number of records. Consider numberOfRecords
  38:         if (ceil > numberOfRecords)
  39:         {
  40:             strSummary.Append(numberOfRecords.ToString());
  41:         }
  42:         else
  43:         {
  44:             strSummary.Append(ceil.ToString());
  45:         }
  46:
  47:         // Displaying Total number of records Creating X of X of About X records.
  48:         strSummary.Append("</b> of About <b>");
  49:         strSummary.Append(numberOfRecords.ToString());
  50:         strSummary.Append("</b>Records</br>");
  51:
  52:
  53:         litPagingSummary.Text =  strSummary.ToString();
  54:
  55:
  56:         //Variable declaration 
  57:         //these variables will used to calculate page number display
  58:         int pageShowLimitStart = 1;
  59:         int pageShowLimitEnd = 1;
  60:
  61:
  62:
  63:         // Just to check, either there is enough pages to implement page number display logic.
  64:         if (pageDispCount > numberOfPages)
  65:         {
  66:             pageShowLimitEnd = numberOfPages; // Setting the end limit to the number of pages. Means show all page numbers
  67:         }
  68:         else
  69:         {
  70:             if (currentPage > 4) // If page index is more then 4 then need to less the page numbers from start and show more on end.
  71:             {
  72:                 //Calculating end limit to show more page numbers
  73:                 pageShowLimitEnd = currentPage + (int)(Math.Floor((decimal)pageDispCount / 2));
  74:                 //Calculating Start limit to hide previous page numbers
  75:                 pageShowLimitStart = currentPage - (int)(Math.Floor((decimal)pageDispCount / 2));
  76:             }
  77:             else
  78:             {
  79:                 //Simply Displaying the 10 pages. no need to remove / add page numbers
  80:                 pageShowLimitEnd = pageDispCount;
  81:             }
  82:         }
  83:
  84:         // Since the pageDispCount can be changed and limit calculation can cause < 0 values 
  85:         // Simply, set the limit start value to 1 if it is less
  86:         if (pageShowLimitStart < 1)
  87:             pageShowLimitStart = 1;
  88:
  89:
  90:         //Dynamic creation of link buttons
  91:
  92:         // First Link button to display with paging
  93:         LinkButton objLbFirst = new LinkButton();
  94:         objLbFirst.Click += new EventHandler(objLb_Click);
  95:         objLbFirst.Text = "First";
  96:         objLbFirst.ID = "lb_FirstPage";
  97:         objLbFirst.CommandName = "pgChange";
  98:         objLbFirst.EnableViewState = true;
  99:         objLbFirst.CommandArgument = "1";
 100:
 101:         //Previous Link button to display with paging
 102:         LinkButton objLbPrevious = new LinkButton();
 103:         objLbPrevious.Click += new EventHandler(objLb_Click);
 104:         objLbPrevious.Text = "Previous";
 105:         objLbPrevious.ID = "lb_PreviousPage";
 106:         objLbPrevious.CommandName = "pgChange";
 107:         objLbPrevious.EnableViewState = true;
 108:         objLbPrevious.CommandArgument = currentPage.ToString();
 109:
 110:
 111:         //of course if the page is the 1st page, then there is no need of First or Previous
 112:         if (currentPage == 0)
 113:         {
 114:             objLbFirst.Enabled = false;
 115:             objLbPrevious.Enabled = false;
 116:         }
 117:         else
 118:         {
 119:             objLbFirst.Enabled = true;
 120:             objLbPrevious.Enabled = true;
 121:         }
 122:
 123:
 124:         //Adding control in a place holder
 125:         plcPaging.Controls.Add(objLbFirst);
 126:         plcPaging.Controls.Add(new LiteralControl("&nbsp; | &nbsp;")); // Just to give some space 
 127:         plcPaging.Controls.Add(objLbPrevious);
 128:         plcPaging.Controls.Add(new LiteralControl("&nbsp; | &nbsp;"));
 129:
 130:
 131:         // Creatig page numbers based on the start and end limit variables.
 132:         for (int i = pageShowLimitStart; i <= pageShowLimitEnd; i++)
 133:         {
 134:             if ((Page.FindControl("lb_" + i.ToString()) == null) && i <= numberOfPages)
 135:             {
 136:                 LinkButton objLb = new LinkButton();
 137:                 objLb.Click += new EventHandler(objLb_Click);
 138:                 objLb.Text = i.ToString();
 139:                 objLb.ID = "lb_" + i.ToString();
 140:                 objLb.CommandName = "pgChange";
 141:                 objLb.EnableViewState = true;
 142:                 objLb.CommandArgument = i.ToString();
 143:
 144:                 if ((currentPage + 1) == i)
 145:                 {
 146:                     objLb.Enabled = false;
 147:                 }
 148:
 149:
 150:                 plcPaging.Controls.Add(objLb);
 151:                 plcPaging.Controls.Add(new LiteralControl("&nbsp; | &nbsp;"));
 152:             }
 153:         }
 154:
 155:         // Last Link button to display with paging
 156:         LinkButton objLbLast = new LinkButton();
 157:         objLbLast.Click += new EventHandler(objLb_Click);
 158:         objLbLast.Text = "Last";
 159:         objLbLast.ID = "lb_LastPage";
 160:         objLbLast.CommandName = "pgChange";
 161:         objLbLast.EnableViewState = true;
 162:         objLbLast.CommandArgument = numberOfPages.ToString();
 163:
 164:         // Next Link button to display with paging
 165:         LinkButton objLbNext = new LinkButton();
 166:         objLbNext.Click += new EventHandler(objLb_Click);
 167:         objLbNext.Text = "Next";
 168:         objLbNext.ID = "lb_NextPage";
 169:         objLbNext.CommandName = "pgChange";
 170:         objLbNext.EnableViewState = true;
 171:         objLbNext.CommandArgument = (currentPage + 2).ToString();
 172:
 173:         //of course if the page is the last page, then there is no need of last or next
 174:         if ((currentPage + 1) == numberOfPages)
 175:         {
 176:             objLbLast.Enabled = false;
 177:             objLbNext.Enabled = false;
 178:         }
 179:         else
 180:         {
 181:             objLbLast.Enabled = true;
 182:             objLbNext.Enabled = true;
 183:         }
 184:
 185:
 186:         // Adding Control to the place holder
 187:         plcPaging.Controls.Add(objLbNext);
 188:         plcPaging.Controls.Add(new LiteralControl("&nbsp; | &nbsp;"));
 189:         plcPaging.Controls.Add(objLbLast);
 190:         plcPaging.Controls.Add(new LiteralControl("&nbsp; | &nbsp;"));
 191:     }
 192:
 193: }
Yes, the code is complex that is why I wrote proper comments which will let you understand the stuff easily.One last thing which is left, is the implementation of dynamically created link button onclick event.
   1: void objLb_Click(object sender, EventArgs e)
   2: {
   3:     plcPaging.Controls.Clear();
   4:     LinkButton objlb = (LinkButton)sender;
   5:     GridView1.PageIndex = (int.Parse(objlb.CommandArgument.ToString()) - 1);
   6:
   7:     managePaging(dt);
   8: }
There it is, we have now completed Custom Paging in Grid View. If you want to download the source code, here is the VS 2008 Solution.Modifications: I have been receiving emails regarding the issues of this post. Especially with the initial five page numbers. I have modified this post to fix the bug it had. Please feel free to point further issues. Also, the download links are also modified.

Datatable to JSON

In this post I will explain you, how can we serialize Datatable to JSON. So that, it can easily pass to JavaScript to get the AJAX done.

First of all fill a Datatable with some results.

DataTable dt = new DataTable();
 
SqlConnection objSqlCon = new SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["AdventureWorksConnectionString"].ToString());
objSqlCon.Open();
 
SqlDataAdapter objSqlDa = new SqlDataAdapter("select * from Production.Product", objSqlCon);
 
objSqlDa.Fill(dt);

Now create a String Builder object that will contain the JSON text and JavascriptSerializer which will serialize the output in JSON.

StringBuilder objSb = new StringBuilder();
JavaScriptSerializer objSer = new JavaScriptSerializer();

Now here we are going to iterate each row and column of data table and put all of them in Dictionary

Dictionary<string, object> resultMain = new Dictionary<string, object>();
int index = 0;
 
foreach (DataRow dr in dt.Rows)
{
    Dictionary<string, object> result = new Dictionary<string, object>();
 
    foreach (DataColumn dc in dt.Columns)
    {
        result.Add(dc.ColumnName, dr[dc].ToString());
    }
    resultMain.Add(index.ToString(), result);
    index++;
}

Notice that, I have created a new dictionary object for every row and finally put all of the dictionaries in Another dictionary I.E. resultMain.

In the end, I have simply Serialize the resultMain Dictionary to render JSON.

A complete post of utilizing Datatable  in JavaScript through AJAX is in the process, I will post that soon.

Authenticated File Access using HTTP Handler.

In this post I will explain you how authenticate the request directly coming to access a file that is downloadable. some thing like *.pdf or *.zip.

Mostly, people make it working by creating an *.aspx page and then write binary of that file in Response.WriteFile. So, user will have no idea where the file is coming from. now this is the fair approach but what if somebody, somehow know the path of downloadable files.

So, to stop the un authenticated access to our files, we will first create a session enable HTTP handler.

public class MyHttpHandler : IHttpHandler, IReadOnlySessionState
{
 
    public void ProcessRequest(HttpContext context)
    {
        if (context.Session["userId"] == null)
        // I am using a session variable you can also use context.User.Identity.IsAuthenticated
        {
            context.Response.Redirect("/login.aspx?retUrl=" + context.Request.RawUrl);
            //Redirecting to the login page ... alternatively you can also set context.Response.StatusCode 
        }
    }
 
    public bool IsReusable
    {
 
        get { return false; }
    }
}

Now, once we have created that. Let me register my newly creater handler for *.zip and *.pdf files in web.config.

 

<httpHandlers>
  <add verb="*" path="*.zip" type="LearningApp.MyHttpHandler, LearningApp"/>
  <add verb="*" path="*.pdf" type="LearningApp.MyHttpHandler, LearningApp"/>
</httpHandlers>

That’s it. If you want more file types to be authenticated add more verbs in handler section of HttpHandler.

Don’t try to put *.* : That can create some serious problem because then each of your *.aspx, *asmx and all your logic stuff will need authentication.

Disable Special Keys in Win App C#

Today, when I was planning to write an article on Grid View. I got a message from a very good friend of mine who is asking to disable the special keys(Windows Keys) in his application. When I start researching on it, I was thinking that it can be done using e.KeyChar but unfortunately, it is not showing any information about windows keys.

So in this post I will explain you, how can we disable the special keys (in our case windows keys) in C# Application.

1. Crete a c# windows application project
2. On the code behind of your default form add the following references

   1: using System.Diagnostics;
   2: using System.Runtime.InteropServices;

3. Now before the constructor of your form place the following code.

   1: // Structure contain information about low-level keyboard input event
   2: [StructLayout(LayoutKind.Sequential)]
   3: private struct KBDLLHOOKSTRUCT
   4: {
   5:     public Keys key;
   6:     public int scanCode;
   7:     public int flags;
   8:     public int time;
   9:     public IntPtr extra;
  10: }
  11:  
  12: //System level functions to be used for hook and unhook keyboard input
  13: private delegate IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam);
  14: [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
  15: private static extern IntPtr SetWindowsHookEx(int id, LowLevelKeyboardProc callback, IntPtr hMod, uint dwThreadId);
  16: [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
  17: private static extern bool UnhookWindowsHookEx(IntPtr hook);
  18: [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
  19: private static extern IntPtr CallNextHookEx(IntPtr hook, int nCode, IntPtr wp, IntPtr lp);
  20: [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
  21: private static extern IntPtr GetModuleHandle(string name);
  22: [DllImport("user32.dll", CharSet = CharSet.Auto)]
  23: private static extern short GetAsyncKeyState(Keys key);
  24:  
  25:  
  26: //Declaring Global objects
  27: private IntPtr ptrHook;
  28: private LowLevelKeyboardProc objKeyboardProcess; 

4. Now add the following code on your constructor.

   1: public Form1()
   2: {
   3:     ProcessModule objCurrentModule = Process.GetCurrentProcess().MainModule; //Get Current Module
   4:     objKeyboardProcess = new LowLevelKeyboardProc(captureKey); //Assign callback function each time keyboard process
   5:     ptrHook = SetWindowsHookEx(13, objKeyboardProcess, GetModuleHandle(objCurrentModule.ModuleName), 0); //Setting Hook of Keyboard Process for current module
   6:  
   7:  
   8:     InitializeComponent();
   9: }

5. Now Implement the callback function

   1: private IntPtr captureKey(int nCode, IntPtr wp, IntPtr lp)
   2: {
   3:     if (nCode >= 0)
   4:     {
   5:         KBDLLHOOKSTRUCT objKeyInfo = (KBDLLHOOKSTRUCT)Marshal.PtrToStructure(lp, typeof(KBDLLHOOKSTRUCT));
   6:  
   7:         if (objKeyInfo.key == Keys.RWin || objKeyInfo.key == Keys.LWin) // Disabling Windows keys
   8:         {
   9:             return (IntPtr)1;
  10:         }
  11:     }
  12:     return CallNextHookEx(ptrHook, nCode, wp, lp);
  13: }

6. Now go to your designer class and replace your dispose method.

   1: /// <summary>
   2: /// Clean up any resources being used.
   3: /// </summary>
   4: /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
   5: protected override void Dispose(bool disposing)
   6: {
   7:     if (disposing && (components != null))
   8:     {
   9:  
  10:         components.Dispose();
  11:     }
  12:     if (ptrHook != IntPtr.Zero)
  13:     {
  14:         UnhookWindowsHookEx(ptrHook);
  15:         ptrHook = IntPtr.Zero;
  16:     }
  17:     base.Dispose(disposing);
  18: }

So, in this way we can stop the windows key operation till your application is running.You can find the VS 2008 Source code here.

Saving and Retrieving File Using FileStream SQL Server 2008

FileStream data type is a very important feature of SQL Server 2008 and gradually getting popular amongst developer for it’s feasibility. And in the past few days specially after “Configure SQL Server 2008 for File Stream” post. I received several feedbacks regarding the usage of FileStream with Ado.net and Frankly there is not much stuff available on Google for this topic.

In this post, I will guide you to use FileStream Data type in Ado.net. But before we start make sure you have configure your SQL Server 2008 instance to use File Stream Data type and for this you can read this post.

Once you finish with the Configuration execute the following script

   1: CREATE TABLE [dbo].[tbl_Files](
   2:     [Id] [uniqueidentifier] ROWGUIDCOL  NOT NULL,
   3:     [SystemNumber] [int] NOT NULL,
   4:     [SystemFile] [varbinary](max) FILESTREAM  NULL,
   5:     [FileType] [varchar](5) NULL,
   6: UNIQUE NONCLUSTERED 
   7: (
   8:     [Id] ASC
   9: )WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
  10: ) ON [PRIMARY] FILESTREAM_ON [FileStreamGroup1]
  11:  
  12: GO
  13:  
  14: ALTER TABLE [dbo].[tbl_Files] ADD  CONSTRAINT [DF_tbl_Files_Id]  DEFAULT (newid()) FOR [Id]

This will create a table with FileStream Data type. Notice the FileType field I have used here to determine the type of file which we will use when we were downloading the file.

Now that we have created a table, lets now move on to the Stored Procedures by which we will access this newly created table.

Security Setting:

Don’t get confused with the heading, there is no additional setting required. You need to do one of the two available options. Either you need to specify “Integrated Security = true” in Connection String or you need to implement Asp.net Impersonation. It is there because SQL Server 2008 will not allow un authenticated user or instance to read/modify the file.

Most of the developers usually aware of Integrated Security stuff but let me give a little detail about asp.net impersonation. Actually, it is a way to Authorize the Instance of your asp.net application on SQL Server by using Credential Information.

Following links will help you to understand or implement impersonation.

http://blogs.msdn.com/shawnfa/archive/2005/03/21/400088.aspx
http://blogs.msdn.com/saurabhkv/archive/2008/05/29/windowsidentity-impersonation-using-c-code.aspx
http://www.west-wind.com/WebLog/posts/1572.aspx

Add Procedure:

Lets create a procedure call it “”FileAdd” and past the following script.

   1: Create PROCEDURE [dbo].[FileAdd]
   2: @SystemNumber int,
   3: @FileType varchar(5),
   4: @filepath varchar(max) output
   5: AS
   6: BEGIN
   7:     -- SET NOCOUNT ON added to prevent extra result sets from
   8:     -- interfering with SELECT statements.
   9:     SET NOCOUNT ON;
  10:  
  11:     DECLARE @ID UNIQUEIDENTIFIER
  12:     SET @ID = NEWID()
  13:  
  14:     INSERT INTO [dbo].[tbl_Files]
  15:     ([Id],[SystemNumber],SystemFile,FileType)
  16:     VALUES (@ID ,@SystemNumber,CAST('' AS VARBINARY(MAX)),@FileType)
  17:     
  18:     select @filepath = SystemFile.PathName() from tbl_Files where Id = @ID
  19:  
  20:     
  21:  
  22: END

In the above procedure, we add new records in our table and just pass empty (null) to the FileStream field because we first want our SQL Server to create an empty file on NTFS location which we can access from our code behind by using the path which we have taken as Output Parameter here.

notice the SystemFile.PathName(), it is a new function introduced in SQL Server 2008 which will return the NTFS location of the file.

 

Get Procedure:

Create a procedure and call it “FileGet”

   1: CREATE PROCEDURE [dbo].[FileGet]
   2: @Id varchar(50)
   3: AS
   4: BEGIN
   5:      select  SystemFile.PathName(),FileType from tbl_Files where Id = @ID
   6: END

This is a simple stuff, we are returning PathName and FileType by specifying ID. Just to read the record.

Upload and Store:

To save the file in the file stream, we will use FileUpload control to upload the file and then save it to FileStream field. For that we have created a page and drag FileUpload control with an Upload button.

Now on the click event of the button write the following code.

   1: byte[] buffer = new byte[(int)FileUpload1.FileContent.Length];
   2: FileUpload1.FileContent.Read(buffer, 0, buffer.Length);
   3:  
   4:  
   5: if (FileUpload1.FileContent.Length > 0)
   6: {
   7:     SqlConnection objSqlCon = new SqlConnection(ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString);
   8:     objSqlCon.Open();
   9:     SqlTransaction objSqlTran = objSqlCon.BeginTransaction();
  10:  
  11:     SqlCommand objSqlCmd = new SqlCommand("FileAdd",objSqlCon,objSqlTran);
  12:     objSqlCmd.CommandType = CommandType.StoredProcedure;
  13:  
  14:     SqlParameter objSqlParam1 = new SqlParameter("@SystemNumber", SqlDbType.Int);
  15:     objSqlParam1.Value = "1";
  16:  
  17:     SqlParameter objSqlParam2 = new SqlParameter("@FileType", SqlDbType.VarChar,4);
  18:     objSqlParam2.Value = System.IO.Path.GetExtension(FileUpload1.FileName);
  19:  
  20:     SqlParameter objSqlParamOutput = new SqlParameter("@filepath", SqlDbType.VarChar, -1);
  21:     objSqlParamOutput.Direction = ParameterDirection.Output;
  22:  
  23:     objSqlCmd.Parameters.Add(objSqlParam2);
  24:     objSqlCmd.Parameters.Add(objSqlParam1);
  25:     objSqlCmd.Parameters.Add(objSqlParamOutput);
  26:  
  27:  
  28:     objSqlCmd.ExecuteNonQuery();
  29:  
  30:     string Path = objSqlCmd.Parameters["@filepath"].Value.ToString();
  31:  
  32:     objSqlCmd = new SqlCommand("SELECT GET_FILESTREAM_TRANSACTION_CONTEXT()", objSqlCon, objSqlTran);
  33:  
  34:     byte[] objContext = (byte[])objSqlCmd.ExecuteScalar();
  35:     
  36:  
  37:     SqlFileStream objSqlFileStream = new SqlFileStream(Path, objContext, FileAccess.Write);
  38:     
  39:     objSqlFileStream.Write(buffer, 0, buffer.Length);
  40:     objSqlFileStream.Close();
  41:  
  42:     objSqlTran.Commit();

Well, in the first two lines we have saved the uploaded file in byte and call this variable “buffer”.
As we are simply using ADO.net, that is why in line 7 and 8 we have created and open a connection. Where as it is worth to mention here, we need to use transaction when we want to do any operation on FileStream field that is why we have begin a new transaction in line no 9.

On line number 11 to 30, we have a simply setup command object and parameter stuff and then execute the procedure and save the output parameter in a variable called “Path”.

This new variable will contain the NTFS location of the file which is stored on SQL Server FileStream. It should be clear that, this file is empty yet as we have not stored any thing in it.

Now on line number 32 we have reused command object and this time we are executing a simple statement “GET_FILESTREAM_TRANSACTION_CONTEXT”. It is also a newly added feature in SQL Server 2008 which will return current transaction context to be used in the next few lines. Now, on line number 34 we have stored the output of the above statement in byte.

In line number 37, here is some thing new which is called “SqlFileStream”. It is a new class which you can find under “System.Data.SqlTypes”. It seems more like FileStream of “System.IO” but it should be cleared here that the file stored in FileStream field cannot be access using regular file stream object of “System.IO” we need to use SqlFileStream to access those files which are stored in FileStream field.

In line no 39 and on, we are writing the file with the content of uploaded file (Remember we have stored our uploaded file in bytes and call it “buffer”). and that’s it.

Read The Stored File:

We have finished with storing the file, now lets see how can we read this file back. To do this, Drag a Grid View and make it similar to the following

   1: <asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" 
   2:        onrowcommand="GridView1_RowCommand">
   3:        <Columns>
   4:            <asp:BoundField DataField="ID" HeaderText="ID" />
   5:            <asp:BoundField DataField="SystemNumber" HeaderText="System Id" />
   6:            <asp:TemplateField>
   7:                <ItemTemplate>
   8:                    <asp:LinkButton ID="lbGetFile" runat="server" CommandName="GetFile" CommandArgument='<%#Eval("ID") %>' Text="Get File"></asp:LinkButton>
   9:                </ItemTemplate>
  10:            </asp:TemplateField>
  11:        </Columns>
  12:    
  13:    </asp:GridView>

And bind the GridView using the following code.

   1: protected void bindData()
   2: {
   3:     SqlConnection objSqlCon = new SqlConnection(ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString);
   4:     objSqlCon.Open();
   5:  
   6:     SqlCommand objSqlCmd = new SqlCommand("Select * from tbl_Files", objSqlCon);
   7:     SqlDataAdapter objSqlDat = new SqlDataAdapter(objSqlCmd);
   8:     DataTable objdt = new DataTable();
   9:     objSqlDat.Fill(objdt);
  10:  
  11:     GridView1.DataSource = objdt;
  12:     GridView1.DataBind();
  13: }

Well, the above markup and the code is enough self explaining but the little important stuff to mention here is the link button. We will use the same link button to download the stored file. Lets quickly move on to the RowCommand implementation of the GridView.

   1: protected void GridView1_RowCommand(object sender, GridViewCommandEventArgs e)
   2: {
   3:     if (e.CommandName == "GetFile")
   4:     {
   5:  
   6:         SqlConnection objSqlCon = new SqlConnection(ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString);
   7:         objSqlCon.Open();
   8:         SqlTransaction objSqlTran = objSqlCon.BeginTransaction();
   9:  
  10:         SqlCommand objSqlCmd = new SqlCommand("FileGet", objSqlCon, objSqlTran);
  11:         objSqlCmd.CommandType = CommandType.StoredProcedure;
  12:  
  13:         SqlParameter objSqlParam1 = new SqlParameter("@ID", SqlDbType.VarChar);
  14:         objSqlParam1.Value = e.CommandArgument;
  15:  
  16:         objSqlCmd.Parameters.Add(objSqlParam1);
  17:         string path = string.Empty;
  18:         string fileType = string.Empty;
  19:  
  20:         using (SqlDataReader sdr = objSqlCmd.ExecuteReader())
  21:         {
  22:             while (sdr.Read())
  23:             {
  24:                 path = sdr[0].ToString();
  25:                 fileType = sdr[1].ToString();
  26:             }
  27:             
  28:         }
  29:         
  30:         objSqlCmd = new SqlCommand("SELECT GET_FILESTREAM_TRANSACTION_CONTEXT()", objSqlCon, objSqlTran);
  31:  
  32:         byte[] objContext = (byte[])objSqlCmd.ExecuteScalar();
  33:  
  34:  
  35:         SqlFileStream objSqlFileStream = new SqlFileStream(path, objContext, FileAccess.Read);
  36:  
  37:         byte[] buffer = new byte[(int)objSqlFileStream.Length];
  38:         objSqlFileStream.Read(buffer, 0, buffer.Length);
  39:         objSqlFileStream.Close();
  40:  
  41:         objSqlTran.Commit();
  42:         Response.AddHeader("Content-disposition", "attachment; filename=" + Path.GetFileName(path) + fileType);
  43:         // Here you need to manage the download file stuff according to your need
  44:         Response.ContentType = "application/octet-stream";
  45:  
  46:         Response.BinaryWrite(buffer);
  47:  
  48:  
  49:         
  50:     }
  51: }

Well, in the first 8 lines, we have created and opened a connection and then begin the transaction. from line no 10 to 28, we are setting the parameter stuff, executing the procedure and save the output in the two variable called “path” and “fileType”.

In line no 30 to 32, we are executing the the transaction context statement and then save the output the bytes. (Same we have done when we were writing the file)

In line no 35 to 40, we have used the same SqlFileStream and instead of writing, we are reading the file this time(notice line no 38) and save the content of the file to the bytes. Now we have file content in bytes, So we have now commit the transaction in line no 41.

In line no 42 and 44, we are setting the content type and specifying the file name with the extension. That is why, we have also saved file type in the database so that at the time of downloading we can make it available in its original state.

And in line no 46, we are simply writing the binary of the file to the browser so that it can be downloaded.

Conclusion:

I have tried my best to explain the integration of FileStream field with ADO.net, and I found this is an easy way to accomplish the task. You can download the VS 2008 solution which contain the complete source code along with procedures and table SQL.

Since, it is a new featured in SQL Server 2008 which is still in CTP by the time I am posting this stuff that is why we can expect some modifications in the method of reading and saving files using FileStream. If somebody face any challenge in the above code. Please feel to contact me.

Validate username using custom validation (AJAX)

In this post, I will explain you how to have an ajax call on custom validator control and check for the username in the database. This task will include two pages one is the form page (default.aspx in our case) in which we have the custom validator and the other one is the page which we call through AJAX to give us the result (validateUser.aspx). You can also have a web service instead of that page but in my scenario , I am using ASPX page.

So, the form will look like as following.

 

   1: <form id="form1" runat="server">
   2: <div>
   3: <asp:Panel ID="pnl1" runat="server" DefaultButton="Button1">
   4:     <asp:TextBox ID="TextBox1" runat="server">
   5:     </asp:TextBox>
   6:     <asp:Button ID="Button1" runat="server" Text="Submit" />
   7:     <asp:HiddenField ID="hfOutput" runat="server" />
   8: </asp:Panel>
   9:     <asp:customvalidator ID="Customvalidator1" runat="server" errormessage="Enter Valid User" ControlToValidate="TextBox1" ClientValidationFunction="ValidMe"></asp:customvalidator>    
  10: </div>
  11: </form>

Default.aspx (Form)

Notice, the hiddent field called hfOutput which we will use to store the output of the AJAX call.

Where as the page which we call through AJAX will look like as follows

   1: <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="validateUser.aspx.cs" Inherits="LearnWebApp.validateUser" %>

validateUser.aspx

In short, we have deleted every thing from this page except page directive. Now if we call this page we will see the simple output without having any HTML tag. we did it because we want to get rid from all the html tags so that we can have a neat and clean output at the time we call this page from Javascript (AJAX). What we want this page to return us is either "True" or "False". If you look at the code behind file of this page you will have a good idea of what we actually upto. Here is the code for that.

   1: protected void Page_Load(object sender, EventArgs e)
   2:         {
   3:             // We can also use a database call here ... right now we are compairing string.
   4:             if (Request.QueryString["username"] == "username")
   5:             {
   6:                 Response.Write("true");
   7:             }
   8:             else 
   9:             {
  10:                 Response.Write("false");
  11:             }
  12:         }

validateUser.aspx.cs

As it is there on comments, here we are only comparing string. You can have a database call and return the result accordingly.

To call the validateUser.aspx from validMe function which we have defined in ClientValidationFunction property of custom validator, we need to write the following javascript on default.aspx

   1: <script type="text/javascript">
   2:         var ajaxCalled = false;
   3:         
   4:         function ValidMe(source, args) {
   5:            callPage(args.Value)
   6:            while (document.getElementById("hfOutput").value != ""){
   7:                 if (document.getElementById("hfOutput").value == "true") {
   8:                     args.IsValid = true;
   9:                 }
  10:                 else {
  11:                     args.IsValid = false;
  12:                 }
  13:                 document.getElementById("hfOutput").value = "";
  14:                 return;
  15:             }
  16:         }
  17:  
  18:         function callPage(strName) {
  19:             var rnd = Math.random() * 1000000;
  20:  
  21:             if (window.XMLHttpRequest) { // Mozilla, Safari, IE7...
  22:                 request = new XMLHttpRequest();
  23:             } else if (window.ActiveXObject) { // IE6 and older
  24:                 request = new ActiveXObject("Microsoft.XMLHTTP");
  25:             }
  26:             var url = 'validateUser.aspx?username=' + strName + '&R=' + rnd;
  27:             request.open("GET", url, true);
  28:             request.onreadystatechange = SetPage;
  29:             request.send(null);
  30:             
  31:         }
  32:  
  33:  
  34:         function SetPage() {
  35:             if (request.readyState == 4) {
  36:                 var objHf = document.getElementById("hfOutput");
  37:                 if (request.status == 200) {
  38:                     if (objHf) {
  39:                         objHf.value = request.responseText;
  40:                     }
  41:                 }
  42:             }
  43:             
  44:         }
  45:     </script>

 

Let me describe what we have done here, I am calling CallPage function from ValidMe which will call from the asp.net validation mechanism. CallPage function is an AJAX call which will call validateUser.aspx and SetPage function will be called once the AJAX call is finish and we have output ready to use.

And on that SetPage function we are setting the Hidden field  called hfOutput to get used by ValidMe function.

That's it ..... :) . You can also download the complete project give below.

Configuration Membership API Asp.net 2.0

Membership API is yet another enhancement from asp.net team. In this post, I will guide you through the configuring of Membership API to the enhanced usage.

So, to get started let me clear one more confusion which most of people have in there mind

They think that Membership API does not use any database behind and asp.net runtime engine perform some miracle at the back end  and all the user information is stored somewhere which is known by runtime engine.

 

That is wrong ..... big WRONG ....

By default, asp.net uses SQL Server as the back end of Membership API. If you have planned to use it, before doing any thing you need to implement the schema of Membership API to your database.

Step 1 (Implement Schema & Configure Database):

To do that, you need to use aspnet_regsql. which can be accessed by the instruction give below.

  • Go to X:\\WINDOWS\\Microsoft.NET\\Framework\\v2.0.50727 (version of dotnet framework can be vary but it should be at least 2.0)
  • Find and execute aspnet_regsql which will appear following screen.

aspnet_regsql_screen1

  • Once you click next, you will be asked to "Configure SQL Server for application services" or "Remove application services information from existing database". You need to select the first one.
  • Select the appropriate database, click next and you are done with the database stuff.

Step 2 (Configure Asp.net Application):

In this step we will configure our existing or new asp.net application to user asp.net membership API.

Please bear in mind that Asp.net Web Application Administration is a very handy and useful tool to check Membership API integration.

Now, to use API you need to specify the connection string of the database which we have configured with aspnet_regsql.

  • Add the following connection string in web.config
   1: <add name="ConnectionString" connectionString="Data Source=SAMHEAVEN;Initial Catalog=Northwind;User Id=sa;Password=usam;"
   2:      providerName="System.Data.SqlClient" />
  • Specify membership and role configuration under system.web of web.config.
   1: <roleManager enabled="true">
   2:    <providers>
   3:      <clear/>
   4:      <add name="AspnetSqlRoleProvider" applicationName="/AppName" connectionStringName="ConnectionString" type="System.Web.Security.SqlRoleProvider"/>
   5:    </providers>
   6:  </roleManager>
   7:  <membership>
   8:    <providers>
   9:      <clear/>
  10:      <add name="AspNetSqlMembershipProvider" type="System.Web.Security.SqlMembershipProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" connectionStringName="ConnectionString" enablePasswordRetrieval="true" enablePasswordReset="true" requiresQuestionAndAnswer="false" applicationName="/DanyTech" requiresUniqueEmail="true" passwordFormat="Clear" maxInvalidPasswordAttempts="5" minRequiredPasswordLength="4" minRequiredNonalphanumericCharacters="0" passwordAttemptWindow="10" passwordStrengthRegularExpression=""/>
  11:    </providers>
  12:  </membership>

 

  • Finally, you need to set authentication type.
   1: <authentication mode="Forms" />

To be descriptive, we have specified settings for two basic parts of Membership API. which is using Connection String called "connectionString" which we have created in the first step.

AspNetSqlMembershipProvider and  AspnetSqlRoleProvider have an attribute called applicationName which is really important. All the information of the Membership API will stored in the database against the applicationName specified here.

Where as, AspNetSqlMembershipProvider have a list of settings. Click here to get the complete list of Membership Provider settings.

Now the configuration stuff is complete. You can check is every thing running fine by clicking on the Asp.net Configuration Icon give right above the solution explorer.

se_config

Go to the security tab and check you can create some users and roles (at least administrator, user) . If not then make sure you have not skipped any step.