SmartCodeGenerator UIProperty for ArrayList of Strings

Note: If you are not familiar with writing UIProperty for SmartCodeGenerator please read this tutorial blog first:

http://community.smartcodegenerator.com/blogs/team_blog/archive/2006/12/02/introducing-new-uiproperty-in-smartcodegenerator.aspx

I recently got a request to be able to handle ArrayList defined in TheProperties.cs.

So the SCG Developer wanted to define string in a ArrayList and wanted to display them during runtime in a combobox, like the one we do with the Enumerator, and wanted to use the selected value in the templates.

Soon I realized this need 3 purposes served

1. Display the list of strings in a combobox at runtime.
2. Know which value the end user has selected and use that in SCGTemplates.
3. Display the PropertyName at runtime.

I cannot use System.Collection.ArrayList directly as it can serve the first purpose but not the second and third at the same time, ArrayList need properties to hold the SelectedValue and PropertyName. So I extended the ArrayList and add extended properties to it.

public class ScArrayList:System.Collections.ArrayList
{
  private string selectedValue;

  public string SelectedValue
  {
    get { return selectedValue; }
    set { selectedValue = value; }
  }

  private string propertyName;
  //Display Name of the Property
  public string PropertyName
  {
    get { return propertyName; }
    set { propertyName = value; }
  }

}

Next Step would be to write a UIProperty for this ScArrayList

ScArrayListUIProperty.ascx
==========================

<%@ Control Language=”C#” AutoEventWireup=”true” CodeFile=”ScArrayListUIProperty.ascx.cs” Inherits=”ScArrayListUIProperty” %>
<table>
<tr>
<td id=”prop”>
<asp:Label ID=”lblPropertyName” runat=”server” Text=”PropertyName” CssClass=”label2″></asp:Label></td>
<td>
<asp:DropDownList ID=”ddProperty” runat=”server”>
</asp:DropDownList></td>
</tr>
</table>

As you can see a DropDownList and a Label control is added.

Here is the Codebehind file content and I ll try to comment the purpose of the codes.

public partial class ScArrayListUIProperty : ScUIPropertyBase
{
  protected void Page_Load(object sender, EventArgs e)
  {

  }

  #region ScFrameworkSpecific

  PropertyInfo propertyInfo = null;
  ScArrayList o = null;
  public ScArrayListUIProperty( )
  { }

  public ScArrayListUIProperty(PropertyInfo propertyInfo)
  {
    //Hooking ArrayListUIProperty_OnPreGenerate to the ParentPage Event
    ParentPage.OnPreGenerate += new EventHandler(ArrayListUIProperty_OnPreGenerate);

    this.propertyInfo = propertyInfo;
    if (propertyInfo.CanRead)
    {
      //Cast the PropertyInfo back to ScArrayList
      o = (ScArrayList)propertyInfo.GetValue(ParentPage.TheProperties, null);
      if (o != null)
      {
        //add each item string object of the ArrayList to the DropDownList
        foreach (string item in o)
        {
          ddProperty.Items.Add(item);
        }
        //Assign the Label.Text with the PropertyName
        lblPropertyName.Text = o.PropertyName;
      }
    }

  }

  public void ArrayListUIProperty_OnPreGenerate(object sender, EventArgs e)
  {

    //Get the SelectedValue from the DropDownList component and set the value
    o.SelectedValue = ddProperty.SelectedValue;

    if (propertyInfo.CanWrite)
    {
      this.propertyInfo.SetValue(ParentPage.TheProperties, o, null);
    }

  }
  #endregion

}

Finally need to map this ScArrayListUIProperty in the PropertyAndUIPropertyMaps.xml
by adding the following node.

<PropertyTypeAndUIPropertyMap>
  <PropertyType>ScArrayList</PropertyType>
  <PropertyUI>ScArrayListUIProperty.ascx</PropertyUI>
</PropertyTypeAndUIPropertyMap>

Thats it we are done.

A Demo TheProperties.cs may look like this:

public class TheProperties
{
  public TheProperties( )
  {
  }

  private ScArrayList testList = new ScArrayList();
  [XmlIgnore]
  public ScArrayList TestList
  {
  get 
  { 
    if (testList.Count == 0)
    {
      testList = new ScArrayList();
      testList.PropertyName = “TestList”
      testList.Add(“test1″);
      testList.Add(“test2″);
      testList.Add(“test3″);
    }
    return testList;
  }
  set
  {
    testList = value;
  }
}

and this should bring up a combobox during the runtime for you to choose an option. 

ASP.NET MembershipApi Cannot resolve collation conflict for equal to operation

In one of our site where we used a ASP.NET Membership API, while deploying to production we started getting “Cannot resolve collation conflict for equal to operation” on the event of Adding Roles to User and Deleting Roles from User. I ll show how I solved it later but lets look at it from step 1 ….

asp.net was throwing out the following error.

Server Error in ‘/’ Application.

Cannot resolve collation conflict for equal to operation.

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.Data.SqlClient.SqlException: Cannot resolve collation conflict for equal to operation.
Source Error:

An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.

Stack Trace:

[SqlException (0x80131904): Cannot resolve collation conflict for equal to operation.]
   System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection) +857338
   System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection) +734950
   System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj) +188
   System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj) +1838
   System.Data.SqlClient.SqlDataReader.ConsumeMetaData() +31
   System.Data.SqlClient.SqlDataReader.get_MetaData() +62
   System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString) +297
   System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async) +886
   System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, DbAsyncResult result) +132
   System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method) +32
   System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior, String method) +122
   System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior) +62
   System.Web.Security.SqlRoleProvider.AddUsersToRolesCore(SqlConnection conn, String usernames, String roleNames) +424
   System.Web.Security.SqlRoleProvider.AddUsersToRoles(String[] usernames, String[] roleNames) +705
   System.Web.Security.Roles.AddUserToRole(String username, String roleName) +341
   RemindRecall.WebApplication.AddUserPage1.CreateUserWizard1_CreatedUser(Object sender, EventArgs e) in C:\Development\RemindRecall\RemindRecall\RemindRecall.WebApplication\AdminPages\AddUserPage1.aspx.cs:52
   System.Web.UI.WebControls.CreateUserWizard.OnCreatedUser(EventArgs e) +105
   System.Web.UI.WebControls.CreateUserWizard.AttemptCreateUser() +341
   System.Web.UI.WebControls.CreateUserWizard.OnNextButtonClick(WizardNavigationEventArgs e) +105
   System.Web.UI.WebControls.Wizard.OnBubbleEvent(Object source, EventArgs e) +453
   System.Web.UI.WebControls.CreateUserWizard.OnBubbleEvent(Object source, EventArgs e) +149
   System.Web.UI.WebControls.WizardChildTable.OnBubbleEvent(Object source, EventArgs args) +17
   System.Web.UI.Control.RaiseBubbleEvent(Object source, EventArgs args) +35
   System.Web.UI.WebControls.Button.OnCommand(CommandEventArgs e) +115
   System.Web.UI.WebControls.Button.RaisePostBackEvent(String eventArgument) +163
   System.Web.UI.WebControls.Button.System.Web.UI.IPostBackEventHandler.RaisePostBackEvent(String eventArgument) +7
   System.Web.UI.Page.RaisePostBackEvent(IPostBackEventHandler sourceControl, String eventArgument) +11
   System.Web.UI.Page.RaisePostBackEvent(NameValueCollection postData) +33
   System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +5102




Version Information: Microsoft .NET Framework Version:2.0.50727.42; ASP.NET Version:2.0.50727.42


I started looking deeper into the problem then I tried to add roles from the ASP.NET Configuration website and still faced the same issue.

Cannot resolve collation conflict for equal to operation. at System.Web.Administration.WebAdminPage.CallWebAdminHelperMethod(Boolean isMembership, String methodName, Object[] parameters, Type[] paramTypes) at ASP.security_users_adduser_aspx.UpdateRoleMembership(String u, CheckBox box) in c:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\ASP.NETWebAdminFiles\Security\Users\addUser.aspx:line 61 at ASP.security_users_adduser_aspx.UpdateRoleMembership(String u) in c:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\ASP.NETWebAdminFiles\Security\Users\addUser.aspx:line 52 at ASP.security_users_adduser_aspx.CreatedUser(Object sender, EventArgs e) in c:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\ASP.NETWebAdminFiles\Security\Users\addUser.aspx:line 13 at System.Web.UI.WebControls.CreateUserWizard.OnCreatedUser(EventArgs e) at System.Web.UI.WebControls.CreateUserWizard.AttemptCreateUser() at System.Web.UI.WebControls.CreateUserWizard.OnNextButtonClick(WizardNavigationEventArgs e) at System.Web.UI.WebControls.Wizard.OnBubbleEvent(Object source, EventArgs e) at System.Web.UI.WebControls.CreateUserWizard.OnBubbleEvent(Object source, EventArgs e) at System.Web.UI.WebControls.Wizard.WizardChildTable.OnBubbleEvent(Object source, EventArgs args) at System.Web.UI.Control.RaiseBubbleEvent(Object source, EventArgs args) at System.Web.UI.WebControls.Button.OnCommand(CommandEventArgs e) at System.Web.UI.WebControls.Button.RaisePostBackEvent(String eventArgument) at System.Web.UI.WebControls.Button.System.Web.UI.IPostBackEventHandler.RaisePostBackEvent(String eventArgument) at System.Web.UI.Page.RaisePostBackEvent(IPostBackEventHandler sourceControl, String eventArgument) at System.Web.UI.Page.RaisePostBackEvent(NameValueCollection postData) at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)



Then I thought it must me a SQL Server Issue as the MembershipAPI is running fine in the development box and giving errors in the production.

I fired up SQL Profiler to look further deep and figured out on the event of adding a role to the user MembershipAPI calling the following StoredProcedure and failing there.

exec dbo.aspnet_UserInRoles_AddUsersToRoles

I opened up the StoredProc in EnterpriseManager and pressed the Check Syntax, I found its coming up with the same error

“Cannot resolve collation conflict for equal to operation”
The same appeared for the following StoredProc as well
dbo.aspnet_UserInRoles_RemoveUsersToRoles

I started doing more research on the StoredProcs and figured out the following line is the culprit…

DECLARE @tbNames table(Name nvarchar(256) NOT NULL PRIMARY KEY)


After doing more googling on the specific problem we figured out there is a Collate Problem in the SQL Server Database. I checked the master database found the
collation name: Latin1_General_CI_AS
where our database collation name was different
collation name: SQL_Latin1_General_CP1_CI_AS


then I explicitly mention Collate similiar to the master database in the statement and changed the line to

DECLARE @tbNames table(Name nvarchar(256) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL PRIMARY KEY)


That solved the problem… Yaaaaaaaaaaaaaaaaay

Summary

I changed 2 Asp.NET Membership API related StoredProc …

aspnet_UsersInRoles_RemoveUsersFromRoles
aspnet_UsersInRoles_AddUsersToRoles


this is the line which caused the issue for me.

DECLARE @tbNames table(Name nvarchar(256) NOT NULL PRIMARY KEY)

I changed and explicitly mentioned the COLLATE similiar to our master database in production server

DECLARE @tbNames table(Name nvarchar(256) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL PRIMARY KEY)

It works fine now….

Hope this helps….

ASP.NET, Javascript tips: Encrypt /Sign /Verify signed message using Capicom ActiveX

This demonstrates possibilities on encrypting, signing, verifying message using the Capicom ActiveX and javascript in a webbrowser. An ASP.NET developers can take note of this technique when you want to invoke to capicom dll to implement PKI infastructure using a browser. I know .NET SmartClient would have been another option where you can use the .NET Framework Libraries to deal with X509Certificates, but you might want to know this technique too:

Source Blog: http://www.feed-squirrel.com/index.cfm?evt=viewItem&ID=36269

  • Use a Memory store and in a web page signs and verifies the sign
  • Create an VB ActiveX with the following code and register it. Also, the CAPICOM dll must be registered. Both activeX could be downloaded from a web site)
  • This code imports a PKCS#12 issued by a subordinader CA. If you want to get it contact me.

Function sign(text As String, P12Path As String, P12Password As String) As String

   ‘ This function imports a PKCS#12 container (private key and certificate to a
   ‘ memory store

    Dim store As store
    Dim signedData As signedData
    Dim signer As signer

    Set signer = New signer
    Set signedData = New signedData
    Set store = New store

    store.Open CAPICOM_MEMORY_STORE, “My”, CAPICOM_STORE_OPEN_READ_WRITE
    store.Load P12Path, P12Password, CAPICOM_KEY_STORAGE_DEFAULT

    signedData.Content = text
    signer.Certificate = store.Certificates.Item(1)

    szSignedData = signedData.sign(signer, True, CAPICOM_ENCODE_BASE64)
    sign = szSignedData
End Function

  • Create a Web Page with the following javascript functions, invoking those from buttons

function btnSignedData_OnClick()
  {
    var SignedData = new ActiveXObject(“AutomaticSign.ASign”);

  try
  {
   txtSignedData.value = SignedData.Sign(txtPlainText.value,”c:\\c.p12″,”1111″);
  }
  catch (e)
  {
   alert(“An error occurred when attempting to sign the content);
   return false;
  }
  }
  function btnVerifyData_OnClick()
   {
    var CAPICOM_CERT_INFO_SUBJECT_SIMPLE_NAME = 0;
    var CAPICOM_CERT_INFO_ISSUER_SIMPLE_NAME = 1; 
    var CAPICOM_VERIFY_SIGNATURE_ONLY = 0;
   // instantiate the CAPICOM objects
   var certificate = new ActiveXObject(‘CAPICOM.Certificate’);
   var SignedData = new ActiveXObject(‘CAPICOM.SignedData’);
   try
   {
    SignedData.Content=txtPlainText.value;
   SignedData.Verify(txtSignedData.value, true, CAPICOM_VERIFY_SIGNATURE_ONLY);
   certificate=SignedData.Certificates(2);
    txtSignerData.value=”Certificate :” + certificate.GetInfo(CAPICOM_CERT_INFO_SUBJECT_SIMPLE_NAME) + “\n”;
    txtSignerData.value+= “Issuer     :” + certificate.GetInfo(CAPICOM_CERT_INFO_ISSUER_SIMPLE_NAME);
   }
   catch (e)
   {
    alert(e.description);
    return false;
   }
  alert(“Signature verified”);
 }