Tuesday, December 23, 2008

Write locked - read shared file

I wanted to open/create a file in one process which locks it for writing but shared for reading which another process can open for reading. It took a while to me. The code is given below:

1) Open a file locked for writing but shared for reading:
FileStream stream = new FileStream(@"C:\Myfile.txt", FileMode.Open, FileAccess.ReadWrite, FileShare.Read);

2) In another process/thread, open the file for read (not writing) and readwrite sharing
FileStream stream = new FileStream(@"C:\Myfile.txt", FileMode.Open, FileAccess.Read, FileShare.ReadWrite)

Friday, November 7, 2008

IPSEC policy update

Click Start, click Run, type in: cmd, click OK
Type: gpupdate /force /sync and press enter.
If they get a permissions error, do the following instead:
Type net stop policyagent and press enter. The policy agent should now stop, this may take a few minutes.
Type net start policyagent and press enter. The policy agent should now start.

Monday, July 7, 2008

Dynamically seting a link to a CSS file in ASP.NET

To dynamically set css file, add runat = server and modify this from the page load:

<head>
<link id="MyStyleSheet" rel="stylesheet" type="text/css" runat="server" />
</head>

Then in your Page_Load, simply add a "href" attribute as below:

Sub Page_Load(Sender As Object, E As EventArgs)
If Not (IsPostBack)
MyStyleSheet.Attributes.Add("href","/css/flostyle.css")
End If
End Sub


Another way to achive the same is by adding a literal control to the page. The literal contains the link to the css file:

void Page_Load(object sender, EventArgs e)
{
Literal l = new Literal();
l.Text = "<link rel=\"stylesheet\" href=\"mystyle.css\" type=\"text/css\" />";
l.ID = "mystyle";
if(Page.Header.FindControl(l.ID) == null)
Page.Header.Controls.Add(l);
}

Thursday, June 19, 2008

IIS: HTTP 500 Internal Server Error

HTTP 500 Internal Server Error

If you are facing this IIS error with either of the following events, this post might help you in resolving the issue.

1. The server failed to load application '/LM/W3SVC'. The error was 'The specified metadata was not found.
2. The server failed to load application '/LM/W3SVC/1/Root'. The error was 'Class not registered

a) Make sure Ditributed Transaction Coordinator service is running. If you are facing problem in making it work, this link might help. In brief, start the service using service MMC; run msdtc -resetlog if it fails. Check your application again. If you are fortunate enough, your problem might have resolved. If not, follow next step.

b) Follow the following steps. These steps have been taken from this site.

This error is caused by the component services on the computer. To resolve the error

Click Start menu (Windows) - Settings - Control Panel.

Double-click Administrative Tools.

Double-click Component Services.

Expand the Computers folder, open the My Computer folder, and select COM+ Applications.

If an error occurs when you try to open the My Computer folder, refer to the following Microsoft article: http://support.microsoft.com/?id=301919

Delete the following IIS-related packages contained in the COM+ Applications folder:

IIS In-Process Applications

IIS Out-of-Process Pooled Applications

IIS Utilities

Open Windows command prompt, navigate to %windir%\system32\inetsrv directory and enter the following commands:

c:\> rundll32 wamreg.dll, CreateIISPackage

Note: This command is case-sensitive.

C:\> regsvr32 asptxn.dll

c:\> IISRESET

Friday, May 2, 2008

Disabling webpart personalization

The webpart personalization can be disabled using:

1) Set Enabled property of the Webpart manater personalization provider:
WebPartManager1.Personalization.Enabled = false;

2) Disable it while declaring the webpart manager in the .aspx page
<asp:webpartmanager runat="server" id="wpmgr1"
personalization-enabled="false" />

Webpart personalization infrastructure

Read the following post which is mostly taken from MSDN, if you are having problem due to ASP.NET personalization provider. This might be required when you are trying to dynamically add/delete webparts and the inconsistent behaviour is observed; specifically when user logs in.

WebPartPersonalization implements low level personalization infrastructure.

This class implements the logic required to carry out lower-level personalization operations. Although the WebPartManager class manages the high-level life cycle of personalization, it is the WebPartPersonalization class that is responsible for actually implementing the physical steps necessary to carry out specific personalization actions. The WebPartPersonalization class in turn relies on an implementation of PersonalizationProvider to communicate with the underlying data store for personalization information.

The WebPartPersonalization class works closely with a WebPartManager control and the rest of the personalization infrastructure.

If you want to create a personalization subsystem significantly different from that provided by the WebPartPersonalization and the WebPartManager classes, you should create a custom WebPartPersonalization implementation by deriving from WebPartPersonalization and add your own custom logic. Then create a custom WebPartManager implementation by deriving from WebPartManager, add your own custom logic, and override the CreatePersonalization method to return your custom WebPartPersonalization implementation. Because a WebPartManager control makes requests to the personalization infrastructure by way of a WebPartPersonalization instance, the WebPartManager control does not directly interact with or hold references to PersonalizationProvider implementations.

Wednesday, April 16, 2008

Reseting user personalization state

To manage personalization state of users, you must use the PersonalizationAdministration class. The following example shows how te reset state of the current user:


WebPartManager mgr = WebPartManager.GetCurrentWebPartManager(Page);
mgr.Personalization.ResetPersonalizationState();


To reset state of a particular user, use the following code snippet:


For managing user state, refer to http://msdn2.microsoft.com/en-us/library/ms366517.aspx


// Reset the user.
if (! PersonalizationAdministration.ResetUserState("~/Default.aspx", txtUser.Text))
{
Response.Write("The user could not be found or the user has not personalized this page");
}

Wednesday, April 9, 2008

IsInRole issue with FormsAuthentication

If rolemanager is enabled in the web.config, the GenericPrinciple is automatically cast to RolePrincipal dismissing all of the GenericPrincipal's previous set roles. To disable this automatic cast, disable rolemanager in the web.config.

<rolemanager enabled = "false">

Friday, April 4, 2008

Reading/Writing Excel in C# using Interop

Add references to :
Microsoft Excel 10.0/11 Object Library using "add reference->com" tab. The following code shows example of reading and writing the xls:


using System;
using System.Collections.Generic;
using System.Text;
using Excel;

namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
string path = @"C:\Documents and Settings\shivps\Desktop\cbit_codef\CBIT_CODEF\New Microsoft Excel Worksheet.xls";
Excel.ApplicationClass app = new ApplicationClass();
app.ShowWindowsInTaskbar = false;

Excel.Workbook wb = app.Workbooks.Open(
path,
0,
false,
5,
"",
"",
true,
Excel.XlPlatform.xlWindows,
"\t",
true,
false,
0,
true,
1,
0);

Excel.Worksheet wsAuthor = null;
foreach (Excel.Worksheet ws in wb.Worksheets)
{
if (string.Compare("author", ws.Name, true) == 0)
{
wsAuthor = ws;
break;
}
}

// read all records
int row = 2; // leave first row
while (true)
{
if (((Excel.Range)wsAuthor.Cells[row, 1]).Value2 == null ||
((Excel.Range)wsAuthor.Cells[row, 2]).Value2 == null ||
((Excel.Range)wsAuthor.Cells[row, 3]).Value2 == null ||
((Excel.Range)wsAuthor.Cells[row, 4]).Value2 == null)
{
break;
}
string first = ((Excel.Range)wsAuthor.Cells[row, 1]).Value2.ToString();
string second = ((Excel.Range)wsAuthor.Cells[row, 2]).Value2.ToString();
string login = ((Excel.Range)wsAuthor.Cells[row, 3]).Value2.ToString();
string pass = ((Excel.Range)wsAuthor.Cells[row, 4]).Value2.ToString();

// create user
string status = "pass";
string error = "no error";

// update xls
wsAuthor.Cells[row, 5] = status;
wsAuthor.Cells[row, 6] = error;
row++;
}

wb.Save();
wb.Close(false, null, null);
app.Quit();
}

}
}

Wednesday, April 2, 2008

Setting Title of a dynamic created webpart

My portal adds and deleted webparts dynamically. I was facing difficulty in setting title of dynamically created webparts. Most of the methods somehow did not work. The following did work for me:


Control c = LoadControl(controlName);
c.ID =id;
wp = WebPartManager1.CreateWebPart(c);
this.WebPartManager1.AddWebPart(wp, wz, index);
wz.WebParts[index].Title = title;

Tuesday, April 1, 2008

Dynamic Webparts: missed events and twice load issue

While developing a portal which has dynamic webparts created, it was observed that control events were not firing. Also page_load function was called more than once. These issues got resolved on setting the personalization state dirty after adding or deleting a webpart. The personalization state can be set Dirty by calling WebPartManager SetPersonalizationDirty function. Since this method is protected, it can not be called directly. To call this function, a custom WebPartManager is required. The following explains it.

1) Create a custom WebPartManager which exposes only a single function SetDirty.



using System;
using System.Collections.Generic;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Security.Permissions;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;

namespace Samples.AspNet.CS.Controls
{
public class NewWebPartManager : WebPartManager
{
public NewWebPartManager() { }

public void SetDirty()
{
this.SetPersonalizationDirty();
}
}

}


2) Use the custom webpart in the page as given below:


<%@ Register Namespace="Samples.AspNet.CS.Controls" TagPrefix="sample" %>
...
<sample:NewWebPartManager ID="WebPartManager1" runat="server" >
</sample:NewWebPartManager>

Monday, March 31, 2008

Custom Webpart Personalization Provider

If don't have SQL Server Express installed or want to modify its behaviour, you can create your own personalization provider. To create a custom personalization provider, the following steps are required:

1) Update web.config for custom personalization provider:

<webparts>
<personalization defaultprovider="AspNetTextFilePersonalizationProvider">
<providers>
<add name="AspNetTextFilePersonalizationProvider" type="TextFilePersonalizationProvider">
</providers>
</personalization>
</webparts>

2) Create the personalization provider which should be derived from
PersonalizationProvider. The following is a Example given in the MSDN at http://msdn2.microsoft.com/en-us/library/aa479037.aspx


using System;
using System.Configuration.Provider;
using System.Security.Permissions;
using System.Web;
using System.Web.UI.WebControls.WebParts;
using System.Collections.Specialized;
using System.Security.Cryptography;
using System.Text;
using System.IO;
public class TextFilePersonalizationProvider : PersonalizationProvider
{
}

Add this code in the App_Code folder of your application. It also can be compiled as a library and placed in the bin folder of the application. The following changes are required for that:

1) Update the web.config to include assembly info

<webparts>
<personalization defaultprovider="AspNetTextFilePersonalizationProvider">
<providers>
<add name="AspNetTextFilePersonalizationProvider"
type="TextFilePersonalizationProvider, <strong>CustomProviders</strong>"/>
</providers>
</personalization>
</webparts>

2) compile the assembly. You may need to reference additional assemblies than given below
csc /t:library /out:Samples.AspNet.CS.Controls.dll /r:System.dll /r:System.Web.dll *.cs

Saturday, March 29, 2008

Symmetic Key Encryption using .NET and C#

There are two main types of encryption and decryption algorithms, symmetric and asymmetric. Asymmetric algorithms use a related key-pair to encrypt and decrypt data. One of the keys in the pair is typically called a public key while the other is called a private key. Data encrypted with a public key can only be decrypted with the private key, and vice-versa. PKI (public key infrastructure) is built based on asymmetric algorithm. RSA is a popular asymmetric algorithm.

On the other hand, in symmetric encryption, a secret key or password is used to scramble data. In order to decrypt the scrambled data, the same key has to be used. DES, Triple DES, RC2 and AES or Rijndael are examples of symmetric algorithms. Symmetric encryption algorithms will be discussed in detail here.

DES
It is based on While DES is well most well known, it is also oldest and least secure due to its relatively small key size. in January, 1999, distributed.net and the Electronic Frontier Foundation worked together and where able to break a DES key in 22 hours and 15 minutes using brute force attack..

Triple DES or TDES
The Data Encryption Standard (DES) was developed by an IBM team around 1974 and adopted as a national standard in 1977. It was developed after DES was found susceptible to brute force attack. Triple DES is a minor variation of this standard. Triple DES uses the original DES algorithm literally three times to encrypt data. TDES was chosen as a simple way to enlarge the key space without a need to switch to a new algorithm. In general TDES with three different keys (3-key TDES) has a key length of 168 bits: three 56-bit DES keys (with parity bits 3-key TDES has the total storage length of 192 bits), but due to the meet-in-the-middle attack the effective security it provides is only 112 bits. A variant, called two-key TDES (2-key TDES), uses k1 = k3, thus reducing the key size to 112 bits and the storage length to 128 bits. However, this mode is susceptible to certain chosen-plaintext or known-plaintext attacks and thus it is officially designated to have only 80-bits of security.

RC2
RC2 was designed by Ron Rivest in 1987 and stands for "Ron's Code" or "Rivest Cypher". It was designed as replacement for DES and was sponsored by Lotus. RC2 is a 64 bit block cypher with a variable key size, , from one byte up to 128 bytes. The algorithm is designed to be easy to implement on 16-bit microprocessors

AES or Rijndael
Advanced Encryption Standard (AES), also known as Rijndael, is a block cipher adopted as an encryption standard by the U.S. government. It has been analyzed extensively and is used worldwide. The cipher was developed by two Belgian cryptographers, Joan Daemen and Vincent Rijmen, and submitted to the AES selection process under the name "Rijndael". AES is fast in both hardware and software and requires small memory. It has a fixed block size of 128 bits and a key size of 128, 192, or 256 bits.
Strictly speaking, AES is not exactly Rijndael (although in verbal practice they are used interchangeably) as Rijndael supports a larger range of block and key sizes; AES has a fixed block size of 128 bits and a key size of 128, 192 or 256 bits, whereas Rijndael can be specified with key and block sizes in any multiple of 32 bits, with a minimum of 128 bits and a maximum of 256 bits. The greater the bit size specified, the more difficult it is to break the encryption algorithm and therefore, the more secure your data is

AES Example
public byte[] Encrypt(string text, string password)
{
Rijndael rij = Rijndael.Create();

/// Create Key and IV using PasswordDeriveBytes. The
/// PasswordDeriveBytes class uses an extension of the PBKDF1
/// algorithm defined in the PKCS#5 v2.0 standard to derive bytes
/// suitable for use as key material from a password. The
/// standard is documented in IETF RRC 2898
PasswordDeriveBytes secKey = new PasswordDeriveBytes(password,
Encoding.Unicode.GetBytes(password));

ICryptoTransform encryptor = rij.CreateEncryptor(secKey.GetBytes(32),
secKey.GetBytes(16));

MemoryStream ms = new MemoryStream();

CryptoStream cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write);
byte[] arrayText = Encoding.Unicode.GetBytes(text);
cs.Write(arrayText, 0, arrayText.Length);
cs.FlushFinalBlock();

byte[] encryptedBytes = ms.ToArray();

ms.Close();
cs.Close();

return encryptedBytes;
}

public string Decrypt(byte[] text, string password)
{
Rijndael rij = Rijndael.Create();
PasswordDeriveBytes secKey = new PasswordDeriveBytes(password,
Encoding.Unicode.GetBytes(password));

ICryptoTransform decryptor = rij.CreateDecryptor(secKey.GetBytes(32),
secKey.GetBytes(16));

MemoryStream ms = new MemoryStream(text);

CryptoStream cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Read);

byte[] buffer = new byte[text.Length];
int count = cs.Read(buffer, 0, buffer.Length);

string plainText = Encoding.Unicode.GetString(buffer, 0, count);

return plainText;
}

Wednesday, March 26, 2008

Opening a new window in ASP.NET

The following simple HTML code can be used to open a new windows:

<form id="Form1">
<INPUT Type="button" OnClick="window.open('http://www.google.com')" value="enter">
</form>


If server side control is a must, do the following at the page load:

button1.Attributes.Add("onclick", "window.open('http://www.google.com')");

Using GridView with Custom Collection

I had a requirement of displaying an objct collection returned by a web service. It took a bit of time to understand and display this data in a GridView.

The following gives example of using the grid view in your code. It is using array of MyObject to display information.

1) To display custom columns, add the following code and add the columns from the gridview->properties->columns. Add the first field which will be clicked as buttonField with ButtonType under Appearance group as link. Also select CommanName under Behaviour group as Select. Unless you set it, SelectedIndexChanged event will not fire and RowCommand event should be captured.
2) Add subsequent columns to be shown as BoundField
3) Handle SelectedIndexChanged to handle clicking of a particular row. GridView1.SelectedIndex will give the index of the row clicked. This index into the myAr will give the object details.

using System;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;

public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
MyObject[] myAr = new MyObject[] { new MyObject("1", "1.1"), new MyObject("2", "2.1"), new MyObject("3", "3.3"), new MyObject("4", "4.4") };
System.Collections.ArrayList al = new System.Collections.ArrayList();
al.Add(new MyObject("1", "11"));
al.Add(new MyObject("2", "22"));
al.Add(new MyObject("3", "33"));
GridView1.DataSource = myAr;

GridView1.AutoGenerateColumns = false;
GridView1.DataBind();
}
protected void GridView1_SelectedIndexChanged(object sender, EventArgs e)
{
int index = GridView1.SelectedIndex;
}
}

public class MyObject
{
private string firstName;
private string lastName;

public MyObject(string fn, string ln)
{
FirstName = fn;
LastName = ln;
}

public string FirstName
{
get { return firstName; }
set { firstName = value; }
}

public string LastName
{
get { return lastName; }
set { lastName = value; }
}
}

GridView Code:
tags have been removed due to the blog writer tool:
<asp:GridView ID="GridView1" runat="server" DataKeyNames="FirstName"
onrowcommand="GridView1_RowCommand"
onselectedindexchanged="GridView1_SelectedIndexChanged>
<columns>
<asp:ButtonField CommandName="select" DataTextField="FirstName"
HeaderText="FirstName" Text="Button" /<
<asp:boundfield datafield="LastName" headertext="Lastname"<
</columns<
</asp:GridView>