Wednesday, December 23, 2009

Generate assembly from C# code file dynamically

Simple code for creating the assemblies dynamically from a C# code file.



public bool CompileSource(string sourceFile, string targetAssembly, string [] references)
        {
            // delete existing assembly first
            if (File.Exists(targetAssembly))
            {
                try
                {
                    // this might fail if assembly is in use
                    File.Delete(targetAssembly);
                }
                catch (Exception ex)
                {
                    this.ErrorMessage = ex.Message;
                    return false;
                }
            }

            // read the C# source file
            StreamReader sr = new StreamReader(sourceFile);
            string fileContent = sr.ReadToEnd();
            sr.Close();

            // set up compiler and add required references
            ICodeCompiler compiler = new CSharpCodeProvider().CreateCompiler();
            CompilerParameters parameter = new CompilerParameters();
            parameter.OutputAssembly = targetAssembly;
            foreach(string reference in references)
            {
        parameter.ReferencedAssemblies.Add(reference);
            }
           
            // Do it: Final compilation to disk
            CompilerResults results = compiler.CompileAssemblyFromFile(parameter, sourceFile);

            if (File.Exists(targetAssembly))
                return true;

            // flatten the compiler error messages into a single string
            foreach (CompilerError err in results.Errors)
            {
                this.ErrorMessage += err.ToString() + "\r\n";
            }

            return false;
        }

Alternative to WSDL.exe tool for creating proxy classes from WSDL definition

Here is the code snippet which will help to generate C# proxy classes from WSDL definition without using the WSDL.exe tool


public bool GenerateWsdlProxyClass(string fileName, string generatedSourceFilename,
            string generatedNamespace)
        {
            // erase the source file
            if (File.Exists(generatedSourceFilename))
                File.Delete(generatedSourceFilename);

            FileStream stream = File.Open(fileName, FileMode.Open);

            ServiceDescription sd = null;

            try
            {
                sd = ServiceDescription.Read(stream);
            }
            catch (Exception ex)
            {
                this.ErrorMessage = "Wsdl Download failed: " + ex.Message;
                return false;
            }

            // create an importer and associate with the ServiceDescription
            ServiceDescriptionImporter importer = new ServiceDescriptionImporter();
            importer.ProtocolName = "SOAP";
            importer.CodeGenerationOptions = CodeGenerationOptions.None;
            importer.AddServiceDescription(sd, null, null);

            // Download and inject any imported schemas (ie. WCF generated WSDL)           
            foreach (XmlSchema wsdlSchema in sd.Types.Schemas)
            {
                // Loop through all detected imports in the main schema
                foreach (XmlSchemaObject externalSchema in wsdlSchema.Includes)
                {
                    // Read each external schema into a schema object and add to importer
                    if (externalSchema is XmlSchemaImport)
                    {
                        Uri baseUri = new Uri(fileName);
                        Uri schemaUri = new Uri(baseUri, ((XmlSchemaExternal)externalSchema).SchemaLocation);

                        Stream schemaStream = File.Open(schemaUri.AbsolutePath, FileMode.Open);
                        System.Xml.Schema.XmlSchema schema = XmlSchema.Read(schemaStream, null);
                        importer.Schemas.Add(schema);
                    }
                }
            }

            // set up for code generation by creating a namespace and adding to importer
            CodeNamespace ns = new CodeNamespace(generatedNamespace);
            CodeCompileUnit ccu = new CodeCompileUnit();
            ccu.Namespaces.Add(ns);
            importer.Import(ns, ccu);

            // final code generation in specified language
            CSharpCodeProvider provider = new CSharpCodeProvider();
            IndentedTextWriter tw = new IndentedTextWriter(new StreamWriter(generatedSourceFilename));
            provider.GenerateCodeFromCompileUnit(ccu, tw, new CodeGeneratorOptions());

            tw.Close();
            stream.Close();
            return File.Exists(generatedSourceFilename);
        }

Wednesday, December 9, 2009

Team build definition for WiX project

Here is the settings you need to do for creating team build for WiX projects.
Add the following piece of code in the .proj file;
<PropertyGroup>
    <CustomBeforeWixTargets>$(MSBuildExtensionsPath)\Microsoft\WiX\v3.0\wix.ca.targets</CustomBeforeWixTargets>
  </PropertyGroup>

  <Target Name="Wix">
    <Message Importance="low" Text="Starting WIX build"/>
    <MSBuild Projects="@(WixProjectToBuild)" Properties="OutDir=$(OutDir);SourcePath=$(OutDir);Version=$(AssemblyVersion);FileVersion=$(AssemblyFileVersion);BuildNumber=$(BuildNumber);CustomBeforeWixTargets=$(CustomBeforeWixTargets)" Targets="Rebuild"></MSBuild>
  </Target>
   <!--WIX solutions-->
  <ItemGroup>
    <WixProjectToBuild Include="$(BuildProjectFolderPath)/../../Source_Code/Development/Deployment/AAS.Database.Setup/AAS.Database.Setup.sln" />
  </ItemGroup>


Also ensure that you have the enough configurations set for processor settings;

<ConfigurationToBuild Include="Debug|x86">
      <FlavorToBuild>Debug</FlavorToBuild>
      <PlatformToBuild>x86</PlatformToBuild>
    </ConfigurationToBuild>
 
    <ConfigurationToBuild Include="Debug|Any CPU">
        <FlavorToBuild>Debug</FlavorToBuild>
        <PlatformToBuild>Any CPU</PlatformToBuild>
    </ConfigurationToBuild>

Data Collection Form design in ASP.NET (Input designer XML which can used for CodeSmith template)

Here is the simple code which will create the Form Designer XML in the format shown below which can be used for CodeSmith template to create .ascx and .ascx.cs files.


XML:
<FormDefinition xmlns="http://aas.com.au/FormGen">
  <PageName>zddas</PageName>
  <FormId>asdas</FormId>
  <Sections>
    <Section>
      <SectionTitle>Test Section</SectionTitle>
      <Controls>
        <Control Type="text" Id="txtField" Text="txtField" />
      </Controls>
    </Section>
  </Sections>
</FormDefinition>





Code:
void GenerateInputForCodeSmith()
        {
            XmlDocument doc = new XmlDocument();
            XmlElement rootEle = default(XmlElement);
            XmlElement elt = default(XmlElement);
            XmlElement eltChoice = default(XmlElement);
            XmlAttribute attr = default(XmlAttribute);

            doc.LoadXml("<FormDefinition xmlns=\"http://aas.com.au/FormGen\"></FormDefinition>");
           
            rootEle = doc.CreateElement("PageName");
            rootEle.InnerText = txtPageName.Text;
            doc.DocumentElement.AppendChild(rootEle);

            rootEle = doc.CreateElement("FormId");
            rootEle.InnerText = txtForm.Text;
            doc.DocumentElement.AppendChild(rootEle);

            rootEle = doc.CreateElement("Sections");
            doc.DocumentElement.AppendChild(rootEle);

            XmlElement elt1 = doc.CreateElement("Section");
            rootEle.AppendChild(elt1);

            elt = doc.CreateElement("SectionTitle");
            elt.InnerText = "Test Section";
            elt1.AppendChild(elt);

            XmlElement eltControls = doc.CreateElement("Controls");
            elt1.AppendChild(eltControls);

            Panel p = (Panel)this.form1.FindControl("pnlSection");
            IEnumerable<Section> sections = p.Controls.OfType<Section>();
            Section sec = sections.First<Section>();
            IEnumerable<Field> fields = sec.FindControl("pnlField").Controls.OfType<Field>();
            foreach (Field field in fields)
            {
                elt = doc.CreateElement("Control");
                attr = doc.CreateAttribute("Type");
                attr.InnerText = ((DropDownList)field.FindControl("cboFieldType")).SelectedValue;
                elt.Attributes.Append(attr);
                attr = doc.CreateAttribute("Id");
                attr.InnerText = ((TextBox)field.FindControl("txtFieldName")).Text;
                elt.Attributes.Append(attr);
                attr = doc.CreateAttribute("Text");
                attr.InnerText = ((TextBox)field.FindControl("txtFieldName")).Text;
                elt.Attributes.Append(attr);
                string[] options = ((TextBox)field.FindControl("txtValues")).Text.Split(";".ToCharArray());
                switch (((DropDownList)field.FindControl("cboFieldType")).SelectedValue)
                {
                    case "dropdown":
                        {
                            foreach (string option in options)
                            {
                                eltChoice = doc.CreateElement("option");
                                attr = doc.CreateAttribute("value2");
                                attr.InnerText = option;
                                eltChoice.InnerText = option;
                                eltChoice.Attributes.Append(attr);
                                elt.AppendChild(eltChoice);
                            }
                            break;

                        }
                    case "radio":
                        {
                            foreach (string option in options)
                            {
                                eltChoice = doc.CreateElement("choice");
                                attr = doc.CreateAttribute("value2");
                                attr.InnerText = option;
                                eltChoice.InnerText = option;
                                eltChoice.Attributes.Append(attr);
                                elt.AppendChild(eltChoice);
                            }
                            break;
                        }
                    case "checkbox":
                        {
                            foreach (string option in options)
                            {
                                eltChoice = doc.CreateElement("choice");
                                attr = doc.CreateAttribute("value2");
                                attr.InnerText = option;
                                eltChoice.InnerText = option;
                                eltChoice.Attributes.Append(attr);
                                elt.AppendChild(eltChoice);
                            }
                            break;
                        }
                    default:
                        break;
                }
                eltControls.AppendChild(elt);
            }

            //doc.Save(Server.MapPath("FormDesigner.xml"));
            string output = doc.OuterXml;
            output = output.Replace(" xmlns=\"\"","");
            FileStream fileStream = File.Open(Server.MapPath("FormDesigner.xml"), FileMode.Create);
            System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();
            byte[] bytes = encoding.GetBytes(output);
            fileStream.Write(bytes, 0, bytes.Length);
            fileStream.Close();
            fileStream.Dispose();

        }

Simple code for dynamically adding user controls using + button functionality in ASP.NET

static int i = 0;
        static List<int> count = new List<int>();
       
        protected void Page_Load(object sender, EventArgs e)
        {
          
        }
        protected override void CreateChildControls()
        {
            base.CreateChildControls();
            RebuildFields();
        }
        void RebuildFields()
        {
            foreach (int j in count)
            {
                UserControl uc = (UserControl)Page.LoadControl("Field.ascx");
                uc.ID = "uc" + j;
                pnlField.Controls.Add(uc);
                LiteralControl lc = new LiteralControl();
                lc.ID = "lc" + j;
                lc.Text = "<br/>";
                pnlField.Controls.Add(lc);
                Button btnAddField = new Button();
                btnAddField.ID = "btnAddField" + j;
                btnAddField.Text = "+";
                btnAddField.Click += btnAddField_Click;
                pnlField.Controls.Add(btnAddField);
                              

                lc = new LiteralControl();
                lc.ID = "lc_" + j;
                lc.Text = "<br/>";
                pnlField.Controls.Add(lc);
            }
        }
        protected void btnAddField_Click(object sender, EventArgs e)
        {
            UserControl uc = (UserControl)Page.LoadControl("Field.ascx");
            i = i + 1;
            count.Add(i);
            uc.ID = "uc" + i;
            pnlField.Controls.Add(uc);
            LiteralControl lc = new LiteralControl();
            lc.ID = "lc" + i;
            lc.Text = "<br/>";
            pnlField.Controls.Add(lc);
            Button btnAddField = new Button();
            btnAddField.ID = "btnAddField" + i;
            btnAddField.Text = "+";
            btnAddField.Click += btnAddField_Click;
            pnlField.Controls.Add(btnAddField);
                       
            lc = new LiteralControl();
            lc.ID = "lc_" + i;
            lc.Text = "<br/>";
            pnlField.Controls.Add(lc);
        }
    }

Friday, December 4, 2009

Settings for using WSPBuilder with MSBuild or TFS Team Build

1) Install the latest WSPBuilder
2) Upload the WSPTools folder to TFS source control
3) Update the "Post Build" event with the one shown below. [Update the path to WSPBuilder.exe accordingly]
IF ("$(OutDir)")==("bin\Debug\") GOTO LocalBuild
 

:TfsBuild
MD "$(TargetDir)bin\Debug\"
COPY "$(TargetDir)*.dll" "$(TargetDir)bin\Debug\"
"D:\TFS Build Location\AAS Web Transform\AAS.DevelopmentBuild\AAS Demo\Sources\Tools\WSPTools\WSPBuilderExtensions\WSPBuilder.exe" -SolutionPath "$(TargetDir)" - OutputPath "$(TargetDir)"
RENAME "$(TargetDir)Debug.wsp" "$(ProjectName).wsp"
RMDIR "$(TargetDir)bin" /S /Q
RMDIR "$(TargetDir)12" /S /Q
GOTO Finish


:LocalBuild
$(TargetDir)..\..\..\..\..\..\Tools\WSPTools\WSPBuilderExtensions\WspBuilder.exe -SolutionPath "$(ProjectDir)" -OutputPath "$(TargetDir)"

:Finish

VSTS Code Analysis Rules for .NET development project

Here is the list of Code Analysis Rules which can be used for any .NET development project.




CA1001
CA1001: Types that own disposable fields should be disposable
CA1009
CA1009: Declare event handlers correctly
CA1016
CA1016: Mark assemblies with AssemblyVersionAttribute
CA1033
CA1033: Interface methods should be callable by child types
CA1049
CA1049: Types that own native resources should be disposable
CA1060
CA1060: Move P/Invokes to NativeMethods class
CA1061
CA1061: Do not hide base class methods
CA1063
CA1063: Implement IDisposable correctly
CA1065
CA1065: Do not raise exceptions in unexpected locations
CA1301
CA1301: Avoid duplicate accelerators
CA1400
CA1400: P/Invoke entry points should exist
CA1401
CA1401: P/Invokes should not be visible
CA1403
CA1403: Auto layout types should not be COM visible
CA1404
CA1404: Call GetLastError immediately after P/Invoke
CA1405
CA1405: COM visible type base types should be COM visible
CA1410
CA1410: COM registration methods should be matched
CA1415
CA1415: Declare P/Invokes correctly
CA1900
CA1900: Value type fields should be portable
CA1901
CA1901: P/Invoke declarations should be portable
CA2000
CA2000: Dispose objects before losing scope
CA2002
CA2002: Do not lock on objects with weak identity
CA2100
CA2100: Review SQL queries for security vulnerabilities
CA2101
CA2101: Specify marshaling for P/Invoke string arguments
CA2108
CA2108: Review declarative security on value types
CA2111
CA2111: Pointers should not be visible
CA2112
CA2112: Secured types should not expose fields
CA2114
CA2114: Method security should be a superset of type
CA2116
CA2116: APTCA methods should only call APTCA methods
CA2117
CA2117: APTCA types should only extend APTCA base types
CA2122
CA2122: Do not indirectly expose methods with link demands
CA2123
CA2123: Override link demands should be identical to base
CA2124
CA2124: Wrap vulnerable finally clauses in outer try
CA2126
CA2126: Type link demands require inheritance demands
CA2136
CA2136: Members should not have conflicting transparency annotations
CA2140
CA2140: Transparent code must not reference security critical items
CA2147
CA2147: Transparent methods may not use security asserts
CA2207
CA2207: Initialize value type static fields inline
CA2212
CA2212: Do not mark serviced components with WebMethod
CA2213
CA2213: Disposable fields should be disposed
CA2214
CA2214: Do not call overridable methods in constructors
CA2216
CA2216: Disposable types should declare finalizer
CA2220
CA2220: Finalizers should call base class finalizer
CA2229
CA2229: Implement serialization constructors
CA2232
CA2232: Mark Windows Forms entry points with STAThread
CA2235
CA2235: Mark all non-serializable fields
CA2236
CA2236: Call base class methods on ISerializable types
CA2237
CA2237: Mark ISerializable types with SerializableAttribute
CA2238
CA2238: Implement serialization methods correctly
CA2240
CA2240: Implement ISerializable correctly
CA2242
CA2242: Test for NaN correctly
CA1000
CA1000: Do not declare static members on generic types
CA1002
CA1002: Do not expose generic lists
CA1020
CA1020: Avoid namespaces with few types
CA1031
CA1031: Do not catch general exception types
CA1051
CA1051: Do not declare visible instance fields
CA1053
CA1053: Static holder types should not have constructors
CA1500
CA1500: Variable names should not match field names
CA1709
CA1709: Identifiers should be cased correctly
CA1726
CA1726: Use preferred terms
CA1804
CA1804: Remove unused locals
CA1811
CA1811: Avoid uncalled private code
CA1820
CA1820: Test for empty strings using string length
CA1822
CA1822: Mark members as static
CA1823
CA1823: Avoid unused private fields
CA2200
CA2200: Rethrow to preserve stack details
CA2201
CA2201: Do not raise reserved exception types
CA1007
CA1007: Use generics where appropriate
CA1011
CA1011: Consider passing base types as parameters
CA1050
CA1050: Declare types in namespaces
CA1054
CA1054: URI parameters should not be strings
CA1055
CA1055: URI return values should not be strings
CA1056
CA1056: URI properties should not be strings
CA1505
CA1505: Avoid unmaintainable code
CA1506
CA1506: Avoid excessive class coupling
CA1800
CA1800: Do not cast unnecessarily
CA1802
CA1802: Use literals where appropriate
CA1814
CA1814: Prefer jagged arrays over multidimensional


Code to create .xoml file from WF workflow using C#

Here is the simple code to create .xoml file from WF workflow;


using (XmlWriter writer = XmlWriter.Create(@"D:\Temp\MyWorkflow.xoml"))
            {
                WorkflowMarkupSerializer serializer = new WorkflowMarkupSerializer();
                SimpleWorkFlow sm = new SimpleWorkFlow();

                serializer.Serialize(writer, sm);
            }

Invoking WF with Input & Output parameters using C#

Here is the simple code for invoking the WF with Input and Output parameters using C#


Dictionary<string, object>  parameters = new Dictionary<string, object>();
            Employer emp = new Employer();
            emp.FirstName = txtFirstName.Text;
            emp.LastName = txtLastName.Text;
            emp.DOB = txtDOB.SelectedDate;
            emp.Email = txtEmail.Text;
            parameters["Emp"] = emp;
            using (WorkflowRuntime workflowRuntime = new WorkflowRuntime())
            {
                AutoResetEvent waitHandle = new AutoResetEvent(false);
                workflowRuntime.WorkflowCompleted += delegate(object sender1,
                    WorkflowCompletedEventArgs e1)
                {
                    lblResult.Text = e1.OutputParameters["Result"].ToString();
                    waitHandle.Set();
                };

                workflowRuntime.WorkflowTerminated += delegate(object sender2,
                    WorkflowTerminatedEventArgs e2)
                {
                    lblResult.Text = e2.Exception.Message;
                    waitHandle.Set();
                };

                WorkflowInstance instance =
                    workflowRuntime.CreateWorkflow(typeof(EmployerWorkFlow), parameters);

                instance.Start();

                waitHandle.WaitOne();
            }

Collecting Data from web parts and submitting to back end using C#

There can be scenarios, wherein you may have to collect data from various web parts in a page and submit to back end. One solution will be to use Connected Web parts feature. Or the sample code below also will help to achieve this;


1) Define one base class
public abstract class IBaseForm : WebPart
    {

    }



2) Implement this class in all the web parts whose data need to be collected
public class InputForm2 : IBaseForm
    {
        protected override void CreateChildControls()
        {
            base.CreateChildControls();
            TextBox t1 = new TextBox();
            t1.ID = "LastName";
            t1.Text = "Last Name";
            this.Controls.Add(t1);
        }
    }



3) This is the piece of code which will collect the data from all the web parts which implement the base class
public class SubmitButton : WebPart
    {
        TextBox t1 = new TextBox();
        protected override void CreateChildControls()
        {
            base.CreateChildControls();
            Button b1 = new Button();
            b1.ID = "submitData";
            b1.Text = "Submit Data";
            b1.Click += new EventHandler(b1_Click);
            this.Controls.Add(b1);

            t1.ID = "result";
            this.Controls.Add(t1);
        }

        void b1_Click(object sender, EventArgs e)
        {
            t1.Text = string.Empty;
            System.Web.UI.ControlCollection colls = this.Parent.Controls;
            IEnumerable bf= colls.OfType();
            foreach (IBaseForm f in bf)
            {
                t1.Text = t1.Text + GetValue(f);
            }
        }

        string GetValue(IBaseForm f)
        {
            string res = string.Empty;
            TextBox t = default(TextBox);

            foreach (System.Web.UI.Control c in f.Controls)
            {
                if (c.GetType().Equals(typeof(TextBox)))
                    t = c as TextBox;
                break;
            }
            res = t.Text;
            return res;
        }
    }

Wednesday, December 2, 2009

To disable "Use command line option '/keyfile' or appropriate project settings instead of 'AssemblyKeyFile'"

This is what will help to avoid this warning;


// disable warning about using /keyfile instead of AssemblyKeyFile
#pragma warning disable 1699
[assembly: AssemblyKeyFile(@"..\AAS.Portal.snk")]
#pragma warning restore 1699

Friday, November 20, 2009

GroupBy and SUM using LINQ in C#

public class Test : IEnumerable<Test>
    {
        public string ColName
        {
            get;
            set;
        }

        public int ColVal
        {
            get;
            set;
        }

        #region IEnumerable<Test> Members

        public IEnumerator<Test> GetEnumerator()
        {
            throw new NotImplementedException();
        }

        #endregion

        #region IEnumerable Members

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            throw new NotImplementedException();
        }

        #endregion
    }





Code to execute:


List<Test> tests = new List<Test>();

            Test test = new Test();
            test.ColName = "A";
            test.ColVal = 123;
            tests.Add(test);

            test = new Test();
            test.ColName = "A";
            test.ColVal = 10;
            tests.Add(test);

            test = new Test();
            test.ColName = "B";
            test.ColVal = 231;
            tests.Add(test);

            var query1 = from t in tests
                         group t by t.ColName into gr
                         select new
                         {
                             Id = gr.Key,
                             Sum = gr.Sum(r => r.ColVal)
                         };
            foreach (var grp in query1)
            {
                Console.WriteLine("{0}\t{1}", grp.Id, grp.Sum);
            }

Thursday, November 19, 2009

Configuring SSL for WCF services

Please follow these steps for configuring the SSL for WCF services


1.     Create and Install the Certificate on the server for Transport Security
2.     Install the Certificate on the client for Client Authentication
3.     Configure the wsHttpBinding with Certificate Authentication and Transport Security
<system.serviceModel>
    <bindings>
      <wsHttpBinding>
        <binding name="wsHttpEndpointBinding">
          <security mode="Transport">
            <transport clientCredentialType="Certificate" />
          security>
        binding>
      wsHttpBinding>
    bindings>
    <client/>
    <services>
      <service behaviorConfiguration="ServiceBehavior"
      name="MyService">
        <endpoint binding="wsHttpBinding"
        bindingConfiguration="wsHttpEndpointBinding"
        name="wsHttpEndpoint" contract="IService" />
        <endpoint address="mex" binding="mexHttpBinding"
        contract="IMetadataExchange"/>
      service>
    services>
      system.serviceModel>
4.     Configure the mex Endpoint to Use wsHttpbinding with Certificate Authentication Configuration
<endpoint address="mex" binding="wsHttpBinding" bindingConfiguration="wsHttpEndpointBinding"
 name="mexEndpoint" contract="IMetadataExchange" />
5.     Configure the Virtual Directory to Use SSL and require Client Certificates
a.     Open the IIS
b.    Right the website where the WCF service is hosted
c.     Select the Directory Security tab
d.    Click “Edit Secure Communications”
e.     Click “Require Secure Channel (SSL)” and click “Require Client Certificates”
Now we can open the hosted WCF service over SSL channel.

For client applications to be able to consume this service, its application configuration file should like as shown below;
<configuration>
  <system.serviceModel>
    <client>
      <endpoint
      behaviorConfiguration="ClientCertificateBehavior"
      binding="wsHttpBinding"
      bindingConfiguration="Binding1"
      contract="IMetadataExchange"
      name="https" />
    client>
    <bindings>
      <wsHttpBinding>
        <binding name="Binding1">
          <security mode="Transport">
            <transport clientCredentialType="Certificate" />
          </security>
        </binding>
      </wsHttpBinding>
    <bindings>
    <behaviors>
      <endpointBehaviors>
        <behavior name="ClientCertificateBehavior">
          <clientCredentials>
            <clientCertificate findValue="CN=clienttempcert"
            storeLocation="CurrentUser"
            storeName="My"
            x509FindType="FindBySubjectDistinguishedName" />
          clientCredentials>
        behavior>
      endpointBehaviors>
    behaviors>
  system.serviceModel>
configuration>