August 22, 2019

C# - How to create List of Anonymous Type objects

Many times you need to create a temporary list of anonymous type objects. For small tasks, like binding a list to a DropDownList control. At that moment you don't want to define a separate class just to keep two properties (i.e. Id & Name) and bind it to the DropDownList's DataSource.

There could be numerous ways to define list of anonymous types and all of these need to infer type from somewhere. I will write some of them here which you can use to create generic list.

  1. First create the object(s) of anonymous type and then pass it to an array and call ToList() method.

       var o1 = new { Id = 1, Name = "Foo" };
       var o2 = new { Id = 2, Name = "Bar" };
    
       var list = new[] { o1, o2 }.ToList();
      
  2. Define a list of dynamic and then populate with anonymous objects.

       List<dynamic> list = new List<dynamic>();
       var o1 = new { Id = 1, Name = "Foo" };
       var o2 = new { Id = 2, Name = "Bar" };
    
       list.Add(01);
       list.Add(02);
      
  3. Define a generic method accepting params T[], and return new List<T>. Pass objects of anonymous type to this method and it will create the List<T>.

       //Define method
       public static List<T> CreateList<T>(params T[] items)
       {
         return new List<T>(items);
       }
    
       //create anonymous objects and call above method
       var o1 = new { Id = 1, Name = "Foo" };
       var o2 = new { Id = 2, Name = "Bar" };
       var list = CreateList(o1, o2);
      
  4. You can use Select() method on Enumerable.Range() to project anonymous objects and then call ToList() method. Once empty list is created, then start adding objects.

       var list = Enumerable.Range(0, 0).Select(e => new { Id = 0, Name = ""}).ToList();
       list.Add(new { Id = 1, Name = "Foo" } );
       list.Add(new { Id = 2, Name = "Bar" } );
      
  5. Enumerable.Repeat() method can also do the trick.

       var list = Enumerable.Repeat(new { Id = 0, Name = "" }, 0).ToList();
       list.Add(new { Id = 1, Name = "Foo" } );
       list.Add(new { Id = 2, Name = "Bar" } );
      
  6. Select() projection method can also use on simple string.

       var list = "".Select( t => new {Id = 0, Name = ""} ).ToList();
       list.Add(new { Id = 1, Name = "Foo" } );
       list.Add(new { Id = 2, Name = "Bar" } );
      

August 19, 2019

Select XML Nodes with XML Namespaces from an XmlDocument and XDocument

To select XML Nodes with Namespace we have to use type XmlNamespaceManager. The AddNamespace() method of XmlNamespaceManager object takes two arguments: one is prefix and the second is the Uri.

Let's say we have following xml:

 <md:ProductOutput xmlns:cb="http://mydomain.com/report/">
   <md:Header>
  <md:Child1 SubjectStatus="">
   Some text for Child1
  </md:Child1>     
   </md:Header>
   <md:Body DocumentID="356d6d32-5755-4ffb-a8b8-8932577526dd">
  <md:Child2>
   Some test for Child2
  </md:Child2>
   </md:Body>
 </md:ProductOutput>

Using XmlDocument:

When selecting nodes from XmlDocument object, you have to use an instance of XmlNamespaceManager class. To select the node md:Header, we will pass the XmlNamespaceManager's instance to SelectSingleNode method of XmlDocument.

XmlDocument xmlDocument = new XmlDocument();
xmlDocument.LoadXml(xmlString); // xmlString variable contains above xml

XmlNamespaceManager nsmgr = new XmlNamespaceManager(xmlDocument.NameTable);
nsmgr.AddNamespace("md", "http://mydomain.com/report/");

XmlNode nodeHeader = xmlDocument.SelectSingleNode("//md:Header", nsmgr);
//nodeHeader contains the required node

Using XDocument:

To select the node elemment from XDoocument, we have to concatenate node name (Header) with the XNamespace and pass this to Element() method of XDocument.Root Element.

var xdoc = XDocument.Parse(xmlString); // xmlString variable contains above xml
XNamespace ns = "http://mydomain.com/report/";

var elementHeader = xdoc.Root.Element(ns + "Header");
//elementHeader contains the required element

July 24, 2019

The remote server returned an error: (411) Length Required

Problem:

If you submit a post request using HttpWebRequest API without setting request body, you will receive following error message:

 System.Net.WebException: 'The remote server returned an error: (411) Length Required.'

For example, If you are making post request with this code:

 string requestedUrl = "http://localhost:13940/MyForm.aspx";
 var request = (HttpWebRequest)WebRequest.Create(requestedUrl);
 request.Method = "POST";
 request.ContentType = "application/x-www-form-urlencoded";

 using (var resp = (HttpWebResponse)request.GetResponse())
 {
  //do your work with response
 }

You will get the above error.

Solution:
  • First, if you are not sending any data in request body, then using the GET method instead will be a good approach.

       string requestedUrl = "http://localhost:13940/MyForm.aspx";
       var request = (HttpWebRequest)WebRequest.Create(requestedUrl);
       request.Method = "GET";
      
  • Second thing is, somehow if you are willing to use POST method and you are not sending any data, then set ContentLength property of the request object to 0, you just have to add this line:

       request.ContentLength = 0;
      
  • Finally, if you need to post some data in the request body, then you must specify the data you are sending as well as length of the data. So the code segment will be like this:

       string requestedUrl = "http://localhost:13940/MyForm.aspx";
       var request = (HttpWebRequest)WebRequest.Create(requestedUrl);
       request.Method = "POST";
       request.ContentType = "application/x-www-form-urlencoded";
       
       //setup data to post
       string postData = "param1=value1¶m2=value2¶m3=value3";
       ASCIIEncoding encoding = new ASCIIEncoding();
       byte[] data = encoding.GetBytes(postData);
       //set content length
       request.ContentLength = data.Length;
       
       //write data to request stream
       var requestStream = request.GetRequestStream();
       requestStream.Write(data, 0, data.Length);
       requestStream.Close();
    
       using (var resp = (HttpWebResponse)request.GetResponse())
       {
         //do your work with response
       }
      

Any of the above change would make your request successfull.

July 15, 2019

The directory '/App_GlobalResources/' is not allowed because the application is precompiled

Problem:

You may encounter the following error message while deploying ASP.NET Web Forms application.

The directory '/App_GlobalResources/' is not allowed because the application is precompiled
Solution:

The solution I found is simply delete the PrecompiledApp.config file and re-start your application.

In some cases, bin folder in deployed website may also cause an error, so you may also need to delete bin folder.

Caution!

Make sure you took the backup before deleting anything.

June 24, 2019

MS SQL Server - Add a column with default value to an existing table

This post describes how to add new column to existing table in SQL Server by using Transact-SQL .

Syntax:

 ALTER TABLE {TABLENAME} 
 ADD {COLUMNNAME} {TYPE} {NULL|NOT NULL} 
 CONSTRAINT {CONSTRAINT_NAME} DEFAULT {DEFAULT_VALUE}
 {WITH VALUES}

Example:

ALTER TABLE Item
        ADD StockQty INT NULL --Or NOT NULL.
 CONSTRAINT DF_Item_StockQty --default constraint name
    DEFAULT (0)--default value
WITH VALUES --Add if Column is Nullable and you want the Default Value for Existing Records.

Lets review the above statement:

  • Item is the target table name, to which I want to add the column.
  • StockQty is the new column name being added, with type INT, also you can specify it as Nullable or NOT NULL.
  • DF_Item_StockQty is the optional constraint name given to the default constraint, if you do not specify name here, it will auto-generate a name like DF_Item_StockQty_6DF5C21B0A
  • DEFAULT (0): 0 is the default value for new column in this example.
  • WITH VALUES is only needed when your new column is Nullable and you want to update existing records with the provided default value (0 in this example). If your Column is NOT NULL, then it will automatically update existing records with the provided default value, whether you specify WITH VALUES or not.

How Inserts work with a Default-Constraint:

  • If you insert a record into table Item and do not specify StockQty's value, then it will be set to the default value 0.
  • If you insert a record and specify StockQty's value as NULL (and your column allows nulls), then the Default-Constraint will not be used and NULL will be inserted as the Value.

References: