Creating custom HTML Helper Extension to generate Grid in ASP.NET MVC

In this article I will show the way of writing a custom HTML helper in ASP.NET MVC project to generate grid at runtime. Although, there are many JQuery controls and third party controls available that provide grid management functionalities but in certain cases you have to design controls to handle specific logic and conditions.

In one of my project I designed a grid control using TagBuilder that generates a grid at runtime on html page. I used Knockout and Knockout extensions to generate view model from the model associated to the view page. (Please note: in the below code snippets I have used Knockout and followed Knockout syntax for data binding and grid generation. You can learn knockout here)

First of all I created an HTMLExtension class marked as static. In ASP.NET MVC there are some out of the box HTML helpers provided like TextBoxFor, LabelFor etc. In order to generate our own HTML tags that work just like the standard HTML helpers provided in ASP.NET MVC framework we have to meet below conditions

  1. Class containing the HTML Helper method should be static
  2. First parameter should be preceded with this HtmlHelper;     indicates the HtmlHelper class that the extension method extends

Following is a code snippet of the custom Grid generation Html Helper method

 


public
static
IHtmlString GridFor<TModel>(this
HtmlHelper<TModel> htmlHelper, String modelView, Type type)

{

 


TagBuilder controlBuilder = new
TagBuilder(“table”);

controlBuilder.Attributes.Add(“style”, “border:1px;”);


var properties = type.GetProperties();

 

#region Header


TagBuilder thead = new
TagBuilder(“thead”);


TagBuilder rowHeader = new
TagBuilder(“tr”);


foreach (var property in properties)

{


var attrHeader = property.CustomAttributes.Where(i => i.AttributeType == typeof(Common.Facade.GridColumnAttribute)).ToList();


if (attrHeader.Count != 0)

{


var attributeHeader = attrHeader[0];


if (Convert.ToBoolean(attributeHeader.ConstructorArguments[1].Value) == false)

{


TagBuilder col = new
TagBuilder(“td”);

col.InnerHtml = attributeHeader.ConstructorArguments[0].Value.ToString();

rowHeader.InnerHtml += col.ToString();

}

}

}

thead.InnerHtml += rowHeader.ToString();

controlBuilder.InnerHtml = thead.ToString();

#endregion

 

#region Rows and Columns

 


TagBuilder tbody = new
TagBuilder(“tbody”);

tbody.Attributes.Add(“data-bind”, “foreach: “ + modelView);

tbody.Attributes.Add(“style”, “width:100″);


TagBuilder row = new
TagBuilder(“tr”);


foreach (var property in properties)

{


var attr = property.CustomAttributes.Where(i => i.AttributeType == typeof(Common.Facade.GridColumnAttribute)).ToList();


if (attr.Count != 0)

{


var attribute=attr[0];


if (Convert.ToBoolean(attribute.ConstructorArguments[1].Value) == false)

{


TagBuilder col = new
TagBuilder(“td”);

col.Attributes.Add(“data-bind”, “text: “ + property.Name);

row.InnerHtml += col.ToString();

}

}

}

tbody.InnerHtml += row.ToString();

controlBuilder.InnerHtml += tbody.ToString();

#endregion

 


return
MvcHtmlString.Create(controlBuilder.ToString());

}

 

On the index.cshtml page I have used Knockout to create view models on the fly

<script
type=”text/javascript”>

ModelService.Persons = @Html.Raw(Json.Encode(ViewBag.Persons));

</script>

 

ModelService.Persons represents the collection view model of the list shipped in ViewBag

 

Finally, you can place following line on your html page to render Grid at runtime.

 

@Html.GridFor(“ModelService.Persons”,typeof(Person))

 


In order to change the look and feel of the plain grid, you can define styles using css to the table rows and columns.

The above grid HTML helper method generates the column name based on the property name. In order to define custom column names we can define custom attribute and annotate that on each property of the properties Class. Below is a sample code snippet of the custom attribute containing few properties.

[AttributeUsage(AttributeTargets.Property)]


public
class
GridColumnAttribute : Attribute

{

 


public
string GridColName { set; get; }

 


public
bool IsHidden { set; get; }

 


public GridColumnAttribute(String Name, bool isHidden)

{


this.GridColName = Name;


this.IsHidden = isHidden;

}

 

}

We can annotate this attribute on our Person class like below (Note: Person is our Model class)


public
class
Person

{

[GridColumn("Id", true)]


public
int Id { set; get; }

 

[Required]

[GridColumn("Name", false)]

[StringLength(10, ErrorMessage="Length cannot exceed to 10 character")]


public
string Name { set; get; }

 

[GridColumn("Department", false)]


public
string Department{set;get;}

 

 


public
String EditLink { get { return
“Person/Edit/” + Id; } }

 


public
String DeleteLink { get { return
“Person/Delete/” + Id; } }

}

In the above code the EditLink and DeleteLink properties are defined to provide row level edit and delete options.

The extended version of the custom Grid HTML Helper method that supports row level editing, deleting and user defined column naming is as follows

 

public
static
IHtmlString GridFor<TModel>(this
HtmlHelper<TModel> htmlHelper, String modelView, Type type)

{

 


TagBuilder controlBuilder = new
TagBuilder(“table”);

controlBuilder.Attributes.Add(“style”, “border:1px;”);


var properties = type.GetProperties();

 

#region Header


TagBuilder thead = new
TagBuilder(“thead”);


TagBuilder rowHeader = new
TagBuilder(“tr”);


foreach (var property in properties)

{


var attrHeader = property.CustomAttributes.Where(i => i.AttributeType == typeof(Common.Facade.GridColumnAttribute)).ToList();


if (attrHeader.Count != 0)

{


var attributeHeader = attrHeader[0];


if (Convert.ToBoolean(attributeHeader.ConstructorArguments[1].Value) == false)

{


TagBuilder col = new
TagBuilder(“td”);

col.InnerHtml = attributeHeader.ConstructorArguments[0].Value.ToString();

rowHeader.InnerHtml += col.ToString();

}

}

}

thead.InnerHtml += rowHeader.ToString();

controlBuilder.InnerHtml = thead.ToString();

#endregion

 

#region Rows and Columns

 


TagBuilder tbody = new
TagBuilder(“tbody”);

tbody.Attributes.Add(“data-bind”, “foreach: “ + modelView);

tbody.Attributes.Add(“style”, “width:100″);


TagBuilder row = new
TagBuilder(“tr”);


foreach (var property in properties)

{


var attr = property.CustomAttributes.Where(i => i.AttributeType == typeof(Common.Facade.GridColumnAttribute)).ToList();


if (attr.Count != 0)

{


var attribute = attr[0];


if (Convert.ToBoolean(attribute.ConstructorArguments[1].Value) == false)

{


TagBuilder col = new
TagBuilder(“td”);

col.Attributes.Add(“data-bind”, “text: “ + property.Name);

row.InnerHtml += col.ToString();

}

}

}

 


TagBuilder editTd = new
TagBuilder(“td”);


TagBuilder editLink = new
TagBuilder(“a”);

editLink.Attributes.Add(“data-bind”, “attr: {href: EditLink}”);

editLink.InnerHtml = “Edit”;

editTd.InnerHtml += editLink.ToString();

 

row.InnerHtml += editTd.ToString();

 


TagBuilder deleteTd = new
TagBuilder(“td”);


TagBuilder deleteLink = new
TagBuilder(“a”);

deleteLink.Attributes.Add(“data-bind”, “attr: {href: DeleteLink}”);

deleteLink.InnerHtml = “Delete”;

deleteTd.InnerHtml += deleteLink.ToString();

 

row.InnerHtml += deleteTd.ToString();

 

tbody.InnerHtml += row.ToString();

 

controlBuilder.InnerHtml += tbody.ToString();

#endregion

 


return
MvcHtmlString.Create(controlBuilder.ToString());

}

 

Now when you run the extended version following Grid will be generated.

Hope this helps!

Signing Outgoing Messages in BizTalk Server using AS2 protocol

In this article I will show to send encrypted and signed message to destination trading partner in BizTalk Server.

I was working on some project earlier this month in which we have to send EDI documents using AS2 protocol. I will not go into the detail of setting up an AS2 protocol and targeting to the audience who are already familiar with BizTalk Server EDI messaging and protocols like AS2 and X12.

For each source and destination trading partners we have to create two parties one for source and one for destination and using those parties you can create agreements. When creating an agreement you have a choice whether to use X12, AS2 or EDIFACT protocol. Here I have used AS2 protocol. Each protocol have different set of attributes and methods to send messages.

Message can be signed using Certificates in BizTalk. You can create a test certificate using Visual Studio command line utility makecert. Certificate is a combination of private/public key pairs. For all outgoing messages BizTalk uses the private key to sign the messages and public key to encrypt the messages.

  • The private key .pfx file has to be imported in the Current User/Personal/Certificates folder.
  • The public key .cer file has to be imported in the Local Computer/Other People/Certificates folder.

Now you have to enable the encryption and sign options on the Validation tab of the Agreement window.

 

 

Make sure to restart the application instance. The message will be encrypted and signed using the private public key of the certificates.

 

 

 

 

Creating Custom Formatter in ASP.NET Web API TO HANDLE SPECIFIC formatted REQUEST

In this article I will show you how to create a custom formatter in ASP.Net Web API to send object in Request body with specific format.

This is a series of the article I wrote earlier in which I showed the way of handling formatted response. http://ovaismehboob.wordpress.com/2014/01/04/creating-custom-formatter-in-asp-net-web-api-for-specific-formatted-response/

Formatters in ASP .NET Web API plays an important role, when the request comes to the server, depending on the media-type, determines which formatter has to be used to parse the request and assemble the data into appropriate format as response. In ASP.Net Web API when the request is made by the user, Web API framework checks if it is Simple Type or a Complex Type. All types like string, integers, etc. are simple types and by default ASP.Net Web API read those values from URI and uses Model binding. On the other hand for complex types, ASP.Net WEB API framework read it from request body by default (the behavior can be overridden) an depending on the content-type load specific formatter from the list of formatters available in HttpConfiguration list.

Let suppose we want to send object in pipe format. In this post I will send a user object in request body in below format.

User object have two properties namely Name and Position and we need to send data in below format

Request Body: Name=Ovais | Position=Technical Architect

This can be done by implementing a custom formatter. When you are creating a custom formatter in ASP.Net Web API, you have two options one is when the request is arrived on server and you want to return the data in specific format or when the request arrives and you want to read/parse the data in specific format.

Steps to follow.

  1. Create a new Web API project in Visual Studio
  2. Add a new User class having two string properties namely Name and Position
  3. Add a new folder named “Infrastructure”. It’s always a good practice to place all the core level classes in particular folder. In my case I have named it Infrastructure.
  4. Add a new class and named it PipeFormatter
  5. Derive this class from BufferedMediaTypeFormatter
  6. Override CanReadType and ReadToStream methods and add the logic to handle incoming request
  7. Below is the complete code of PipeFormatter class


public class PipeFormatter : BufferedMediaTypeFormatter
{
public PipeFormatter() {
SupportedMediaTypes.Add(new System.Net.Http.Headers.MediaTypeHeaderValue(“text/pipe”)); }

public override bool CanReadType(Type type)
{
if (type == typeof(User)) {
 return true;

}
return false

}

public override object ReadFromStream(Type type, System.IO.Stream readStream, System.Net.Http.HttpContent content, IFormatterLogger formatterLogger, System.Threading.CancellationToken cancellationToken) {

 User userObject = new User();

 StreamReader reader = new StreamReader(readStream);

 string str=reader.ReadToEnd();

 String[] propArr = str.Split(new char[] { ‘|’ });

 foreach (var val in propArr) {
string[] propIntArr = val.Split(new char[] { ‘=’ });
if (propIntArr[0].ToLower().Trim().Equals(“name”)){
userObject.Name = propIntArr[1].ToString();
}
else if (propIntArr[0].ToLower().Trim().Equals(“position”)) {
userObject.Position = propIntArr[1].ToString();
}
}
return userObject;
}
}

 8. In the above code you can see that I have added the “text/pipe” media type in the supported media type list. This you have to add it so you can specify the Content-Type attribute when sending HTTP request.

 9. Now open the WebApiConfig class placed under App_Start folder

 10. Add an entry in the config.Formatters collection as below.

config.Formatters.Add(new WebApplication1.Infrastructure.PipeFormatter));

 11. Build the project and run.

 12. In order to test I used Fiddler
13. Requesting from fiddler
 

14. ReadFromStream method is called and populate the User object


15. And finally on my controller Post method I am receiving this object.
 

Hope this helps!

Providing Interactive Grid handling in ASP.Net MVC Application using Kendo UI

Nowadays, in every application, grid plays an important role in providing rich and easy interface for data management. In my last project I used Telerik Kendo UI Grid control for ASP.Net which I found quite easy and robust to use with ASP.NET MVC applications. Developers only need to provide some configuration and the rest of features like paging, sorting, filtering editing, updating, etc. runs accordingly. Moreover, there are lot of different skins available which you can apply depending on your UI design.

Following are the steps shows the usage of Telerik Kendo UI Grid control in ASP .NET MVC applications with a minimal amount of code.

  1. Create a new ASP.Net MVC Web Application in Visual Studio
  2. Make sure you have installed the Telerik ASP.NET MVC Controls suite from telerik website.
  3. In your MVC project add a reference to Kendo.MVC.dll from C:\Program Files (x86)\Telerik\UI for ASP.NET MVC Q1 2014\wrappers\aspnetmvc\Binaries\Mvc5
  4. Under the Scripts folder add kendo.all.min.js and kendo.aspnetmvc.min.js files from C:\Program Files (x86)\Telerik\UI for ASP.NET MVC Q1 2014\JS
  5. Then, create another folder Styles under root MVC project and add three files and a Default folder containing images for telerik controls.

    - kendo.common.min.css

    - kendo.dataviz.min.css

    - kendo.default.min.css

  6. Open BundleConfig.cs file and add entries to newly added Kendo CSS files and Javascript files.

    bundles.Add(new
    ScriptBundle(“~/bundles/kendoUI”).Include(


“~/Scripts/kendo.all.min.js”,


“~/Scripts/kendo.aspnetmvc.min.js”));


bundles.Add(new
StyleBundle(“~/Content/css”).Include(


“~/Content/bootstrap.css”,


“~/Content/site.css”,


“~/Styles/kendo.common.min.css”,


“~/Styles/kendo.dataviz.min.css”,


“~/Styles/kendo.dataviz.default.min.css”));

7. Now open the _Layout.cshtml as this is the default master page in ASP.Net MVC application and add the newly configure kendo bundle in the head section as below

@Scripts.Render(“~/bundles/kendoUI”)

8. Now let’s create a new controller named “DemoController”

 

9.  Create a sample model class that contains few properties

public
class
Person
{

public
Int32 Id { set; get; }

public
String Name { set; get; }

public
String Company { set; get; }

public
String Designation { set; get; }

public
String EmailAddress { set; get; }
}

10. Then in the newly added DemoController add a GetPersons method that returns the list of persons to display in a view.


public
class
DemoController : Controller

{


// GET: Demo


public
ActionResult GetPersons([DataSourceRequest] DataSourceRequest request)

{


List<Person> personLst = new
List<Person>();

personLst.Add(new
Person { Id = 1, Name = “Ovais Mehboob”, Company = “USTS”, Designation = “Technical Architect”, EmailAddress = “ovaismehboob@yahoo.com” });

personLst.Add(new
Person { Id = 1, Name = “Khusro Habib”, Company = “EO”, Designation = “SAP Lead”, EmailAddress = “n/a” });

personLst.Add(new
Person { Id = 1, Name = “David”, Company = “USTS”, Designation = “Network Administrator”, EmailAddress = “n/a” });


return Json(personLst);

}

}

11. Create a Index method that returns ActionResult. As per the default routing engine this will be invoked whenever the controller will be called without action name

12. Add a new empty view by right clicking the Index method

13. Add the html.kendo grid code as shown below in the Index.cshtml page

@using System.Collections;

@using Kendo.Mvc.UI;

<h2>Persons</h2>

@(Html.Kendo().Grid<DemoKendo.Models.Person>()

.Name(“grid”)

.Columns(columns =>

{

columns.Bound(p => p.Name).Width(200).Title(“Name”);

columns.Bound(p => p.Company).Width(300).Title(“Company”);

columns.Bound(p => p.Designation).Width(200).Title(“Designation”);

columns.Bound(p => p.EmailAddress).Width(200).Title(“Email Address”);

})

.HtmlAttributes(new { style = “height: 500px” })

.Editable(editable => editable.Mode(GridEditMode.InCell))

.Pageable()

.Navigatable()

.Filterable()

.Sortable()

.Scrollable()

.ColumnMenu()

.Resizable(resizable => resizable.Columns(true))

.DataSource(dataSource => dataSource

.Ajax()

.Batch(false)

.PageSize(50)

.ServerOperation(false)

.Model(model =>

{

model.Id(p => p.Id);

}

)

.Read(action => action.Action(“GetPersons”, “Demo”))

.Update(“SavePerson”, “Demo”)

)

)

14. If you see the above code the .Read is the method where you can specify the action name followed with a Controller name

15. Likewise read, you can add update and delete methods as well

16. There are many attributes provided which you can configure on the fly like Pageable() for paging, Filterable() for filtering. For detailed documentation for each method please visit telerik.com

17. Once you build and run the project you will see something like below

Hope this helps!

Awarded Microsoft MVP (Most Valuable Professional) Award

I am glad to announce that on 1st July 2014, I received an email from Microsoft on being awarded as the Microsoft MVP (Most Valuable Professional) in ASP.Net/IIS. I got really excited to see the award and that Microsoft has recognized my contributions I did in the community.

I am more impassioned and certainly increases my motivation to contribute more in the community.

I would like to thanks Microsoft for acknowledging my efforts and especially Microsoft Innovation Center, Pakistan for sponsoring my technical sessions/events and giving me opportunity to contribute and participate in Boot camps and Tech Ed events.

Looking forward to continue my efforts and share the knowledge as much as I can to help the community.

Grab eBooks and Videos in a very low price – by Packt Publishing

Being an active participant in reviewing Packt Publishing books related to Software discipline, I would like to celebrate the 10 years completion of Packt and wanted to express the new and exciting promotion in which they are offering all the eBooks and Videos for just $10.

Folks, hurry up and grab some good titles!

Here is a link Packt $10 Offer

 

Common errors in processing EDI documents using BizTalk Server 2013

Following are some errors I encountered while setting up an EDI in BizTalk Server 2013. These are quite common errors but I thought to write a post showing the exact reason of the problem which may help someone configuring EDI.

I will try to keep update this article the more errors I come across so it will be used as a reference.

ERROR 1: Agreement Resolution based on the context properties for x12 Protocol has failed

Resolution:

In order to resolve this error check the Identifiers values in parties agreement and when sending an EDI document specify the exact values that have been set for ISA6 and ISA8 in the identifiers tab of the Source Party agreement. These values should match the value of an EDI document for the same ISA6 and ISA6 properties.



In the above screen shot ISA6 and ISA8 values are PartyA and PartyB and the Sender and Receiver qualifiers are ZZ-Mutually Defined (X12)

So the EDI document header should be something like below

ISA^00^ ^00^ ^ZZ^PartyA ^ZZ^PartyB

 

 

 

ERROR 2: Delimiters are not unique, field and segment separator are the same. The sequence number of the suspended message is 1.

Resolution:

EDI document is fixed length format. This error comes up when the values length exceeded or does not meet the fixed length format. When structuring EDI document its better to define the values properly otherwise sometimes it becomes hard to rectify this type of error.

Follow

Get every new post delivered to your Inbox.

Join 59 other followers

%d bloggers like this: