Wednesday, December 14, 2011

Using ReportViewer Control in ASP.NET MVC



Assembly References (From Visual studio2010 installation folder) :
Microsoft.ReportViewer.Common
Microsoft.ReportViewer.WebForms

Step 1 - Create a view called Report and bind it to strongly type ReportViewModel.


@model ReportViewModel
@{
ViewBag.Title = "Reports";
}

Reports: @Model.Title






Step 2 - Add a WebForm(ReportViewer.aspx) to your Web Project under a folder called Reports. It should have following html code in it.


<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="ReportViewer.aspx.cs" Inherits="Sample.Web.Reports.ReportViewer" %>

<%@ Register assembly="Microsoft.ReportViewer.WebForms, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" namespace="Microsoft.Reporting.WebForms" tagprefix="rsweb" %>




















Code behind

public partial class ReportViewer : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
string ReportName = Request.QueryString["Name"];
if (ReportName != null)
{
string ReportServerURL = Request.QueryString["ServerURL"];
if (ReportServerURL == null)
ReportServerURL = @"http://localhost/reportserver";

rptViewer.ShowParameterPrompts = true;
rptViewer.ProcessingMode = Microsoft.Reporting.WebForms.ProcessingMode.Remote;
rptViewer.ServerReport.ReportServerUrl = new Uri(ReportServerURL);
rptViewer.ServerReport.ReportPath = string.Format("/{0}", ReportName);
}
}
}

Reading .CSV file to DataSet in C#



Pre-Requisites (if you are using 64 bit CPU mode in IIS 7.0

Following code snippet is using Microsoft .Jet.OLEDB.4.0 to read the data from .CSV file. As 64 version of Microsoft.Jet.OLEDB.4.0 is not available, it will throw following exception while running on 64 bit CPU mode in IIS 7.0.


Microsoft .Jet.OLEDB.4.0 not registered on the Local Machine.

Fix – We have to run the Application Pool in "Enable 32 bit Application mode" in IIS7 manager using following steps

1. Right click on the Application Pool and select “Advanced Settings…” or select the same from the Actions pane after selecting the Application pool
2. Change the “Enable 32-bit Applications” to True (if you want the application pool to spawn in a 32-bit mode)
3. Click OK



public static DataSet ReadCSVFile(string directoryName, string filename)
{
string connString = string.Format("Provider=Microsoft.Jet.OLEDB.4.0;Data Source={0};Extended Properties=\"Text;HDR=Yes;FMT=Delimited;IMEX=1;\"", directoryName);
string cmdString = string.Format("SELECT * FROM [{0}]", filename);
DataSet dataSet = null;
using (OleDbDataAdapter dataAdapter = new OleDbDataAdapter(cmdString, connString))
{
dataSet = new DataSet();
dataAdapter.Fill(dataSet);
}

return dataSet;
}

Convert Dictionary object to System.Web.MVC.SelectListItem



Scenario - In ASP.NET MVC, you need Enumberable of SelectListItem object to bind to a DropDownList. But you have a dictionary object of Lookup values from DB. What is the best way to convert dictionary to Enumberable of SelectListItem.

Solution - Create an Extension method ToSelectListItems() which will convert the dictionary object to Enumberable of SelectListItem as follows:


public static IEnumerable ToSelectListItems(this IDictionary items, string selected = "1")
{
return items.Select(k =>
new SelectListItem
{
Selected = (k.Value == selected),
Text = k.Key,
Value = k.Value
});
}

Best way to change the ConnectionString dynamically in C#



Update the connection string dynamically.

using System.Data.SqlClient;
using System.Data.EntityClient;

public virtual string UpdateConnectionString(string database)
{
var _connectionString = "Data Source=.;Initial Catalog=SampleDB;Integrated Security=SSPI;MultipleActiveResultSets=True"
var sqlBuilder = new SqlConnectionStringBuilder(_connectionString);
sqlBuilder.InitialCatalog = database.ToString();
return sqlBuilder.ConnectionString;
}


Change Entity Framework ConnectionString dynamically

public virtual string UpdateEFConnectionString(string newConnectionString)
{
var csBuilder = new EntityConnectionStringBuilder();
csBuilder.ProviderConnectionString = newConnectionString;
return csBuilder.ConnectionString;
}

Best way to compare two objects in C#



Compare 2 instances of the class SubComponent


public class SubComponentSequenceComparer : IEqualityComparer
{
public bool Equals(SubComponent x, SubComponent y)
{
return x.Sequence == y.Sequence;
}

public int GetHashCode(SubComponent obj)
{
return obj.Sequence.GetHashCode();
}
}

Saturday, December 10, 2011

Deploy ASP.NET MVC Application on Azure



Step 1: Install Windows Azure Tools via WebPI. This will install any dependencies that are missing. Here is the link
http://www.microsoft.com/web/gallery/install.aspx?appid=WindowsAzureToolsVS2010



Step 2: Open Visual Studio2010 as an administrator and create an Azure Project.The Azure storage emulator requires administrator privileges.



Step 3: In the next dialog, Add the MVC3 Web Role to the Azure Project.



Step 4: Choose Internet Application Project Template.

Web.Config Configuration for Azure Application - The detault providers (e.g. Membership, Roles, Profile) are configured as universal providers which work with SQL Azure.



Step 5: Create an Azure Hosted Service



In the create Azure Hosted Service, provide following information -



  • Choose a subscription : "Selected your already created subscription"
  • URL Prefix for your service : "My Service"
  • Region : "Choose your region"
  • Deployment Options : Do not deploy (at this point of time, our App is not ready for deploy)

Step 6: Create a SQL Azure Database



View database properties


Step 7: Package the Application for Azure Deployment

  • Open the Web.config file and set the connection string appropriately and make two following changes:

    • Set the password for the database login which was configured previously.
    • Add “MultipleActiveResultSets=True” to the connection string. This setting is required by the Universal Providers used in the MVC 3 application.

  • Now we’re ready to package our application for Azure deployment.



  • The Azure service package and Cloud configuration files will be created and a Windows Explorer window will open up to the folder where the files have been created. Make a note of this directory location. We’ll need it later to find the package to deploy to Azure.

Step 8: Deploy the package on Azure








Happy Programming !

Monday, December 5, 2011

SQL Azure Reporting Services Advantages and Disadvantages



Advantages:

  • Highly available, the cloud services platform has built-in high availability and fault tolerance
  • Scalable, the cloud services platform automatically scales up and down
  • Secure, your reports and SQL Azure databases are on a safe place in the cloud
  • Cost effective, you don’t have to set up servers and you don’t have to invest in managing servers
  • Use the same tools you use today to develop your solutions. Just develop your reports in BIDS or Report Builder and deploy to Azure

Disadvantages are:

  • SQL Azure databases are the only supported data sources in the first version, more data sources are expected to come
  • No developer extensibility in the first version, so no custom data sources, assemblies, report items or authentication
  • No subscriptions or scheduled delivery
  • No Windows Authentication, only SQL Azure username/password is supported in the first version, similar to SQL Azure database. When SQL Azure database gets Windows Authentication, Azure Reporting will follow

What they added in CTP

  • The following new features are available in the new CTP:
  • Improved availability and performance statistics.
  • Ability to self-provision a SQL Azure Reporting server.
  • Windows Azure Management Portal updates to easily manage users and reports deployed to SQL Azure Reporting.
  • Availability of the service in all Microsoft Windows Azure datacenters around the world.
  • Official Microsoft support in this new CTP release.
  • Greater access for customers with no separate registration process required to use the new CTP.
  • developers can now author reports
  • Combined with the SQL Azure Data Sync (also in CTP release), SQL Azure Reporting enalbes new hybrid IT scenarios - for example, customers can schedule automatic synchronization of on-premises databases with SQL Azure, and then deploy cloud-based BI reports based on the synchronized cloud-based data sources.

Sunday, December 4, 2011

Amplify.Request

What is Amplify.Request ?


amplify.request is an abstraction layer that can be used for any kind of request for data. amplify.request sets out to separate the data retrieval and caching mechanisms from data requestors.

Demo Overview  Download

Requesting player list and player details using Amplify.Request.

.JS files


amplify.js
amplify.request.js
amplify.store.js


Amplify calls





HTML View



Amplify Demo



Players list:




   





Player Name:  










References :

http://amplifyjs.com/api/request/

Javascript Knockout

What is Javascript Knockout ?

Knockout is a JavaScript library that makes it easier to create rich, desktop-like user interfaces with JavaScript and HTML, using observers to make your UI automatically stay in sync with an underlying data model. It works particularly well with the MVVM (Model View View Model) pattern.

Demo Overview  Download

A simple scenario - Choose your indian cricket team for the upcoming Australia Serires.

Templating using JS Knockout









HTML View






Players Available :




Selected Players:


















References:
http://knockoutjs.com/

Saturday, November 19, 2011

Link for all materials on MVC from Microsoft



http://msdn.microsoft.com/en-us/library/gg416514(v=vs.98).aspx

Progressively enable the mobile web with MVC4, HTML5 and JQuery Mobile. Here the presentation from Phil Haack, senior program manager, Microsoft.

http://channel9.msdn.com/events/BUILD/BUILD2011/TOOL-803T


Enjoy !!!

Wednesday, November 16, 2011

Populate a Dropdown in MVC

Scenario- How to develop a reusable component to populate all dropdowns in MVC applications.

Design-
Repository class - LookupRepository.cs that will fetch lookup values from DB.
Static Extension class - LookupExtension.cs will have method that will extend Dictionary object and return list of SelectListItems.
Static Helper class - LookupHelper.cs will call the repository, cast the result to list of SelectListItems and build SelectList.

Model class

public class Sample
{
public int Country {get; set;}
public SelectList Countries {get; set;}
}


Controller code

public ActionResult Index()
{
var model = new Sample();
model.Countries = LookupHelper.Countries;
return View(model);
}


Index.chtml code

@model Sample
@Html.DropDownListFor(m => m.Country, Model.Counties, new { @style = "width:86%" })


LookupHelper.cs


public static SelectList Counties
{
get
{
return new SelectList(_lookupRepository.Countries.ToSelectListItems(), "Text", "Value");
}
}

LookupExtensions

public static IEnumerable ToSelectListItems(this IDictionary items, string selected = "1")
{
return items.Select(k =>
new SelectListItem
{
Selected = (k.Value == selected),
Text = k.Key,
Value = k.Value
});
}

Review on Telerik ASP.NET MVC Extensions

We used Telerik ASP.NET MVC Extensions GPL 2.0 in our last project extensively. Beside some initial challenges, we able to successfully delivered the project on time. Some of the coolest controls that we used are: Grid, TabStrip, PanelBar, Window, Numeric, Upload.

The features that I liked the most are:
1. In line editing feature of Grid like ASP.NET Grid control.
2. Client side events like OnLoad, OnEdit, OnDelete etc. supported by Telerik controls.
3. Row level formatting in the Grid.
4. Client/Server Template for bound columns.
5. Upload control supports uploading multiple files.

Challenges-
1. No proper support for Dropdown in inline editing Grid.

Reference : http://demos.telerik.com/aspnet-mvc/

ASP.NET MVC 4 Developer Preview features



Enhancements to Default Project Templates - The Web Site created using Default Project Template gives more modern look.

Mobile Project Template - This is the most important feature in this release. This helps you to create site specifically for mobile and tablet browsers. This is based on JQuery Mobile - open source for touch optimized UI JQuery Mobile Documenation.

MVC 4 Mobile Features

Display Modes - This feature allows the application to select views depending on the browser i.e. Desktop Browser or Mobile. It supports views like _Layout.chtml for Desktop browser, _Layout.mobile.chtml for mobile browser.

Task support for Async Controller - Async Controller returns an Task. The async Controller actions also support timeout.

Azure SDK - Supports for Windows Azure SDK (Sept 2011 1.5)

Looking forward for next release...

Monday, November 14, 2011

How to render Model validation errors on Ajax Calls in ASP.NET MVC

As we all know that Web Development without Jquery & Ajax is an impractical idea. Most of us use Data Annotations for validation purposes. How these Data Annotatation will work on client side when you have Ajax calls in your application. MVC doesn't take care of firing these validations when Ajax calls are made. The below approach can help you handle this situation.

1. MVC generates a spantag i.e. span class="data-valmsg-for=Field Name" for each field that has Html.ValidationMessageFor() in it's markup.
2. Let controller action validates the model and returns you a Json object with all validation messages back to your Ajax call. This collection will have both the Key i.e. Field Name and the validation message.
3. The Ajax call will loop thru this Array and render this messages in the span of appropriate field element.

Base Controller Code


public JsonResult ValidateModel(string status = "")
{
bool isValid = ModelState.IsValid;

return Json(new
{
Valid = isValid,
NewId = 0,
Errors = GetErrorsFromModelState(),
Status = !string.IsNullOrWhiteSpace(status) ?
status :
isValid ? "Success" : "Failure"
});
}

public Dictionary GetErrorsFromModelState()
{
var errors = new Dictionary();

foreach (var key in ModelState.Keys)
{
// Only send the errors to the client.
if (ModelState[key].Errors.Count > 0)
{
errors[key] = ModelState[key].Errors;
}
}

return errors;
}

public void ClearValidationError()
{
foreach (var key in ModelState.Keys)
{
if (ModelState[key].Errors.Count > 0)
{
ModelState[key].Errors.Clear();
}
}
}


Application Contoller Code

public ActionResult Edit(TemplateViewModel model)
{
bool returnStatus = false;
var id = SaveNewTemplate(model);
returnStatus = true;
JsonResult validation = ValidateModel();
return Json(new { success = returnStatus, id = id, message = message, Validation = validation });
}


Cliend side code

$.ajax({
type: "POST",
url: form.attr("action"),
dataType: "json",
async: false,
cache: false,
data: form.serialize(),
success: function (result) {
if (result.success) {
if (result.Validation != null && !result.Validation.Data.Valid) {
$.each(result.Validation.Data.Errors, function (key, value) {
if (value != null) {
var container = $('span[data-valmsg-for="' + key + '"]');
container.removeClass("field-validation-valid").addClass("field-validation-error");
container.html(value[value.length - 1].ErrorMessage);
}
});
}
}
});

How to handle Session Timeout in Jquery calls in MVC

In my last project, we used Jquery Ajax calls severly for almost all postbacks in the application. Then we had this situration - Jquery Ajax calls throwing 503 Server error (Object reference null) all the places on Server Session Expiration. Here how we handled this particular problem.

Step 1 - First came up a extension method which will check if server session expires and the code is as follows:


public static bool IsSessionExpired(this HttpSessionStateBase session)
{
if (session == null || !session.IsNewSession)
{
return false;
}

// If it says it is a new session, but an existing cookie exists, then it must have timed out
string sessionCookie = HttpContext.Current.Request.Headers["Cookie"];
return sessionCookie != null && sessionCookie.Contains("ASP.NET_SessionId");
}


Step 2 - Design an Attribute that will call the above routine on every action executed in any controller of the Application. You can apply this attribute on your BaseController at the class level. The code is as follows:


[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)]
public class SessionExpireAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
base.OnActionExecuting(filterContext);
HttpContext ctx = HttpContext.Current;

// check if session is supported
if (ctx.Session != null)
{
if (filterContext.HttpContext.Session.IsSessionExpired())
{
var viewData = filterContext.Controller.ViewData;
viewData.Model = username;
filterContext.HttpContext.Response.StatusCode = 504;
filterContext.Result = new ViewResult { ViewName = "SessionTimeout", ViewData = viewData };
}
}
}

}


Step 3 - Equip your Ajax Calls with Error Handler that will check for Error Status Code = 504 and redirect the user to SessionTimeout page.


//$.Ajax Get/Post Calls

$("#NewTemplate").live("click", function () {
if (confirmNavigation($(this))) {
$("#selectedTemplateId").val(0);
$.ajax({
type: "GET",
url: Urls.NewTemplate,
async: false,
cache: false,
success: function (cb) {
if (!cb) {
alert("Unable to load the screen");
}
else {
uiChanges = true;
$("#divTemplate").html(cb);
}
},
error: function (xhr, textStatus, errorThrown) {
redirectOnSessionTimeout(xhr.status);
}

});
}
});

//$.load Ajax Calls

function loadAuditTableGrid(name) {
$("#auditTableGrid").load(
Urls.AuditTable,
{ auditTableName: name },
function (response, status, xhr) { redirectOnSessionTimeout(xhr.status); });
}

//$.getJSON way
reqJSON(Urls.CheckForActiveState, { id: selectedId},
function (result) {
if (!result.success)
$("#Message").show();
else
$("#Message").hide();

}, function (xhr, textStatus, errorThrown) {
redirectOnSessionTimeout(xhr.status);
});

function reqJSON(url, params, success, error) {
var CallParams = {};
CallParams.type = params.Method || "POST";
CallParams.url = url;
CallParams.processData = true;
CallParams.data = params;
CallParams.dataType = "json";
CallParams.success = success;
if (error) {
CallParams.error = error;
}
$.ajax(CallParams);
}

function redirectOnSessionTimeout(status) {
if (status == "504") {
location.href = Urls.SessionTimeout;
}
}

Custom validation using MVC3 ValidationAttribute

In this Demo, Let's create a custom validation attribute "DateGreaterAttribute" that validates that a Template EndDate is later than the given StartDate. This validation attribute will be applied like any other Data Annotations.



public partial class Template
{
public Template()
{
}

public int TemplateId { get; set; }
public string Name { get; set; }
public byte Active { get; set; }
public System.DateTime Effective { get; set; }
[DateGreater(DateStartProperty="Effective", ErrorMessage="The Expiration Date must be after the Effective Date")]
public Nullable Expiring { get; set; }
public string Description { get; set; }
public string Notes { get; set; }
public int ChangedBy { get; set; }
public System.DateTime ChangedAt { get; set; }

}

[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
public class DateGreaterAttribute : ValidationAttribute
{
public DateGreaterAttribute() : base("The End Date must be later then Start Date")
{
}
public string DateStartProperty { get; set; }

protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
string dateEndString = (value != null) ? value.ToString() : string.Empty;
if (string.IsNullOrWhiteSpace(dateEndString))
{
// A blank end date means no comparison. Use Required attribute to force an end date entry.
return ValidationResult.Success;
}

// Get the start date and compare to the end date
bool valid = false;
PropertyInfo dateStartPropertyInfo = validationContext.ObjectType.GetProperty (DateStartProperty);

if (dateStartPropertyInfo != null)
{
object dateStartValue = dateStartPropertyInfo.GetValue(validationContext.ObjectInstance, null);
string dateStartString = (dateStartValue != null) ? dateStartValue.ToString() : string.Empty;
DateTime dateStart;

if (DateTime.TryParse(dateStartString, out dateStart))
{
DateTime dateEnd;
if (DateTime.TryParse(dateEndString, out dateEnd))
{
valid = (dateStart < dateEnd);
}
}
}

return valid ? ValidationResult.Success : new ValidationResult(ErrorMessage);
}
}



In the above code, we are implementing a class initializer and IsValid() from the base class. The constructor allows you to provide a default error message in case of validation failure.
The IsValid() method provides 2 parameters,
1. object value - It's the value entered by the user for End Date field.
2. validationContext - Describes the context in which a validation check is performed. The 2 important property that we use here are -
a) ObjectType - Get the type of the object to validate i.e. Template. The GetProperty()method provided by it, returns property information on the Start Date parameter.
b) ObjectInstance - Get the object to validate i.e. Template. This instance is used to get the value of Start Date parameter.

Custom Validation using ASP.NET4 IValidateableObject

Let's pick up the Template class of my previous blog for this demo and implement duplicate Template Name check validation.
The class design of the Template class is as follows:


using System.ComponentModel;
using System.ComponentModel.DataAnnotations;

public partial class Template : IValidatableObject
{
public Template()
{
}

public int TemplateId { get; set; }
public string Name { get; set; }
public byte Active { get; set; }
public System.DateTime Effective { get; set; }
public Nullable Expiring { get; set; }
public string Description { get; set; }
public string Notes { get; set; }
public int ChangedBy { get; set; }
public System.DateTime ChangedAt { get; set; }

public IEnumerable Validate(ValidationContext validationContext)
{
if (this.State == System.Data.EntityState.Added)
{
using (SampleDBEntities db = new SampleDBEntities())
{
if (db.Templates.ToList().Exists(m => m.Name.ToUpper() == this.Name.ToUpper()))
{
yield return new ValidationResult("Duplicate template name", new List { "Name" });
}
}
}
}

}


In the code above, we have implemented the Validate() method of IValidatableObject to check if there is any Template with the same name. The "yield" construct is used to append this validation to other server side validations applied to the Template model class.

Sunday, November 13, 2011

Using EF 4.1 in Web Applications



Scenario - Internet Applications being stateless in nature, how to use the Entity Framework in n-Tier ASP.NET Applications.

Challenge - The biggest challenge of using EF in web applications is - the short lived life cycle of a web page prevents entities from remaining attached to an ObjectContext and providing the required state information of these entities to SaveChanges for updates. While it works fine in scenarios where the Page instantiates an instance of ObjectContext, do the Insert/Update/Delete operations and call the SaveChanges in the same request. At the end of the request, the Page is disposed along with the dependent objects.

But it fails in scenarios where the user makes a series of updates in several requests and finally commit the save operation.

It's easiest to make a call to SaveChanges when you have a long-running ObjectContext that is not an option in the web scenario.

Without the long-running context, there are two possible paths to take.

The first involves persisting the entities in memory on the server-most likely in the user's session. When the user wants to update you can attach those entities to a new context and update them using the new values coming from the controls on the page, then call SaveChanges The downside is scalability when your user base grows.

The second path for allowing SaveChanges to do its job would entail performing the query again prior to saving. You can then update the newly queried entities with the values coming from the client. The state information of entities are supplied from the application logic.

We have taken the second path. Here how we achieved this through coding.

DB Design -
DB Desing


CRUD Operations

public void InsertUpdateTemplate(Template template)
{
using (SampleDBEntities db = new SampleDBEntities (this.EFConnectionString))
{
if (template.Added)
{
db.Templates.Add(template);
}
else
{
var templateEntity = db.Templates.Find(template.TemplateId);
db.Entry(templateEntity).CurrentValues.SetValues(template);
db.Entry(templateEntity).State = template.State;

var fixedDeposites = db.FixedDeposites;
foreach (FixedDeposite deposite in template.FixedDeposites.Where(i => i.State != EntityState.Unchanged))
{
if (deposite.Added)
{
db.Entry(deposite).State = EntityState.Added;
}
else
{
var entity = fixedDeposites.Find(deposite.FixedDepositeId);
db.Entry(entity).CurrentValues.SetValues(deposite);
db.Entry(entity).State = deposite.State;
}
}

var accounts = db.SavingAccounts;
foreach (SavingAccount account in template.SavingAccounts.Where(i => i.State != EntityState.Unchanged))
{
if (account.Added)
{
db.Entry(account).State = EntityState.Added;
}
else
{
var entity = accounts.Find(account.SavingAccountId);
db.Entry(entity).CurrentValues.SetValues(account);
db.Entry(entity).State = account.State;
}
}
}

db.SaveChanges();
}
}

Where :

[MetadataType(typeof(TemplateMetadata))]
public partial class Template : BaseEntity, IValidatableObject
{
}

public class TemplateMetadata
{
//Place for applying Data Annotations on EF generated class.
[Required(ErrorMessage = "Template must have a name")]
public string Name { get; set; }
}

where:

Model Metadata
ASP.NET MVC 2 introduced an extensible model metadata system where developers could implement a class which derived from ModelMetadataProvider to provide meta-information about the models in the system. In ASP.NET MVC 3, You can find the metadata provider findable via the dependency resolver. This is place to apply data annotations on EF generated classes.


public abstract class BaseEntity
{
public abstract bool Added { get; }
public bool Modified { get; set; }
public bool Deleted { get; set; }

public EntityState State
{
get
{
if (this.Added)
{
return EntityState.Added;
}
else if (this.Modified)
{
return EntityState.Modified;
}
else if (this.Deleted)
{
return EntityState.Deleted;
}
return EntityState.Unchanged;
}
}
}


References : http://msdn.microsoft.com/en-us/library/orm-9780596520281-01-21.aspx

Tuesday, September 6, 2011

IIS 404 error while running ASP.NET MVC on IIS 7 (Production)

Fix : ASP.NET MVC dlls are missing. Check if you have following dlls in the bin of deployment folder.

System.Web.MVC
System.Web.Razor
System.Web.Abstractions
Microsoft.Web.Infrastructure
System.Web.WebPages
System.Web.WebPages.Razor
System.Web.WebPages.Deployment
System.Web.Helpers

Unrecognized attribute 'targetFramework'

Scenario - "Unrecognized attribute 'targetFramework'" error while running ASP.NET/ASP.NET MVC Application.

Fix - The AppPool is using a wrong .NET framework. You can check it by following steps.

IIS -> Application Pools -> Double click on "Your Application Pool" -> .NET Framework Version.

Enjoy !!!

Sunday, September 4, 2011

How to configure Code Coverage in TFS 2010

Prerequisite - You should have Visual Studio 2010 Ultimate or Visual Studio 2010 Premium edition.

Step - 1: Create a .testconfig file using Add New Item menu.
Step - 2: Double click the .testconfig file to open Test Settings window.
Step - 3: Choose Data and Diagnostics tab and check you have following settings.
Role - Local Machine only
Code Coverage - Checked
Step - 4: Double click the Code Coverage to open Code Coverage Detail window. Add all your assemblies in this window that should come under code coverage.
Now if you run your tests, you should also see Code Coverage in Code Coverage tab (Test - Windows -> Code Coverage Result)

Wednesday, August 17, 2011

Tips & Tricks of ASP.NET MVC3



RAZOR
Problem 1:


Error: 'string' does not contain a definition for 'jpg'

Fix:



Problem 2:

Twitter : @MyTwitterHandle
Error: 'MyTwitterHandle' does not exist in the current context

Fix:

Twitter : @@MyTwitterHandle

Problem 3:

@{
var persons= "Deba, Ramesh, David";
if (persons.Contains("Deba"))
{
Your name is in the list
}
else
{
Your name isn't in the list
}

Error : ; Expected

Fix:

@{
var persons= "Deba, Ramesh, David";
if (persons.Contains("Deba"))
{
Your name is in the list
}
else
{
Your name isn't in the list
}
}


Problem 4:

@{
var message = "Hello Deba";
message
}
Output: Hello Deba

Fix:

@{
var message = "Hello Deba";
@Html.Raw(message)
}
Output : Hello Deba

Patterns
1. Create extension method of URL Helper
2. Use Bootstraper in Global.asax if you have lot of things in Application_Start
3. Decorate your actions with proper AcceptVerbs and CacheControl.
4. Use Depedency Injection
5. Use Typed Views
6. Async Controllers
7. Avoid having huge numbers registrations in Global.asax. Ulternate is- Use Attribute based Route Mapper. http://maproutes.codeplex.com/
8. Use Post-Redirect-Get pattern

[HttpGet]
public ActionResult Employee()
{
return View("Employee");
}
[HttpPost]
public ActionResult Employee(Employee e)
{
if (!Validate(e))
{
return View("Employee", e);
}
RedirectToAction("AddEmployee");
}

9. No Magic Strings

Using expression based Form generation - Html.TextBoxFor(order=>order.Customer.Name)
Using expression based URL generation - Url.Action(c=>c.Index())
Using expression based RedirectToAction - RedirectToAction(c=>c.Index())

10. Keep your controller free from HttpContent. If you require to use it, then use custom action filter or interface or wrapper.
10. Reusing view logic by using @helper.
Step1 - Create a view in App_Code folder and write all your helper methods.
Ex:

@helper FormatCurrency(Decimal price)
{
@price.ToString("c")
}

Step 2 - Calling the helper method

@FormatCurrency(product.price)


Issue with @helper - Built-in Html helper methods are not available inside the views in App_Code. Fix - http://blogs.msdn.com/b/davidebb/archive/2010/10/27/turn-your-razor-helpers-into-reusable-libraries.aspx


Related Topics -
MVC 3 Tools Update


ASP.NET MVC WebGrid

Friday, August 12, 2011

IIS 7.0 throws the error HTTP Error 503. The service is unavailable

Issue : Default Web Site throws HTTP 500 error. The Service is unavailable.

Cause : Port 80 has been reserved for a named account using netsh command netsh http add urlacl=http://+:80/ user=<>. Port reservation is done to give exclusive access to a particular account on resource such as http port or url. To check list of all reserved port urls, use following netsh command.
netsh http show urlacl

Fix : Remove the port 80 reservation by using following netsh command.
netsh http delete urlacl url=http://+:80/

Thursday, August 11, 2011

IIS related services

From August 12, 2011

Wednesday, August 10, 2011

Publishing WCF Services using IIS and .NET 4.0

1.0 Run the command aspnet_regiis -i to register asp.net 4.0 with IIS, updates both the classic and integrated mode handlers and script mappings in the IIS metabase.
1.1. Open Visual Studio in Run as Administration mode.
2. Right click on the WCF Service Project and choose Publish.
3. In the Publish Web Site Dialog box, choose following settings -
3.1 Publish Method: Web Deploy
3.2 Service Url - Address of the Service through which the publishing happens.
Ex: publishing locally - localhost
3.3 Site/Application - Url of Publish To site Ex: Default Web Site/MyApp. Note - This site should be already created in IIS as an application.
4. By Default the service will be deployed to run as Default App Pool which uses .NET 2.0. and will fail. Therefore, you need to change the App Pool of this Web Site to ASP.NET V4.0 Application Pool.
5. Ensure the Account used for the Application Pool has necessary permission on the resources used by WCF Service like DB Access etc.

Friday, August 5, 2011

Project Management Tips


Situation - What action will you take to achieve code quality ?
1. Keep language specific code review guidelines and Naming Conventions document handy for the developer to refer before he writes any single line of code.
2. Peer Review
3. Code Analysis Tools. Ex: VS2010 Code Analysis, StyleCop, FxCop, NDepend, SPDispose Checker.
4. Code should be unit tested using Tools like NUNIT, Visual Studio Testing Framework.
Situation - Developer unable to deliver as per the estimate/plan.
1. Insufficient training may be one of the issue. What type of training is required ? Domain Knowledge or Technical.
2. Attach a senior resource/domain analyst to guide the developer in his work.
Situation - Large number of UAT issues.
1. Revisit your system test cases. They may not cover the complete functional testing.
2. Engage a Domain Analyst to review the system cases.
Situation- Unplanned leave schedule of the Team is impacting delivery
1. The first activity that a PM should take up at the start of the project is to maintain a leave calendar for the team in a shared location. Team member should update their leave plan well in advance for better planning.
Situation - What is the best way to manage bugs in the System ?
1. Identify a tool to manage bugs or issues.
2. Classify the bugs as per their severity i.e High, Medium and Low.
3. Assignment of bugs to resources as per their severity/complexity.
4. Initial Estimation of bugs/issues by resources.
5. Actual Estimation of bugs/issues by resources.
6. Set the status of the bug i.e. Unable to Reproduce, Code Complete, Closed, Open, Waiting etc. with proper comments.
Situation - Re-open Bugs
1. Root cause analysis.
2. Insufficient Test cases.
Situation - Client has the option to change the requirement anytime during the development.
1. Ensure you have configured your Repository (SharePoint etc.) to send alert whenever there is a change in requirement.
2. Analyze and do an impact analysis as the next step. Artifacts can be impacted - Source Code, Unit Test Cases, System Test Cases, Build Script etc.
3. Impact on estimation
4. Communicate the Client about the impact
5. Implementation of the change of requirement.
Situation - Code coverage/review/refactoring is missing during project execution
1. This is a common problem in software projects. The team miss some important activities like code review/unit testing/refactoring etc. under delivery pressure. There is a need for monitoring the process during the execution and enforce the process to ensure quality delivery. Escalate the issue.

Risk management breakdown in software projects -


Monday, May 30, 2011

How to check if the form passes all ASP.NET validations on client side


$(document).ready(function() {

$("form").submit(function()
{
Page_ClientValidate();
if (Page_IsValid)
{
//Ajax call
}
});


});

How to get SharePoint user profile information from Account Name


using Microsoft.Office.Server;
using Microsoft.Office.Server.UserProfiles;

private string GetPreferredName(string accountName)
{
SPSite site = SPContext.Current.Web.Site;
ServerContext context = ServerContext.GetContext(site);
UserProfileManager profileManager = new UserProfileManager(context);
try
{
UserProfile profile = profileManager.GetUserProfile(accountName);
return profile[PropertyConstants.PreferredName].ToString();
}
catch
{
return accountName;
}
}

Saturday, May 28, 2011

Jquery Progress Notification

In our last project, we had to display a progress notification for the long running processes. After doing some research, we found the pnotify jquery plugin very useful.
It is very easy to implement aswell. Here are the steps of implementation.

This plugin requires 2 files to be downloaded from http://plugins.jquery.com/project/pnotify and they are

1. jquery.pnotify.min.js
2. jquery.pnotify.default.css

And the code goes here:









References:
http://pines.hg.sourceforge.net/hgweb/pines/pnotify/raw-file/tip/index.html
http://plugins.jquery.com/project/pnotify

Confirmation before ASP.NET Asynchronous call

Scenario - Ask for user confirmation before ASP.NET Ajax asynchronous call.

Fix- The ASP.NET Ajax PageRequestManager class fires the initilaizeRequest event before trigger the asynchronous call. The second event of this event is the initializeRequestEventArgs. It has a method called get_postBackElement() that identifies the element that triggered the call.



Clientside callback after ASP.NET Ajax Update Panel refresh



Scenario - How to implement - Calling an clientside method after ASP.NET Ajax refresh. Ex: You have a Jquery plugin to show progress of the current operation. But you also need to call it's remove method after Ajax Update Panel refresh.

Fix -


Monday, May 16, 2011

LINQ Lessons

In our recent project, we came across many situations where we had to write queries on our objects in the UI tier. Few of them are give below.

I am taking here the movie class to explain different Linq queries.
public class Movie
{
     public int ID {get; set;}
     public string Title {get; set;}
  public string Director {get; set;}
     public int Genre {get; set;}
     public int RunTime {get; set;}
     public DateTime ReleaseDate {get; set;}
     public decimal Budget{get; set;}

}

public List GetMovies()
{
return new List {
new Movie{Title="Rocky", Director="Alex", Genre=1, RunTime=180, ReleaseDate ="01/01/1990"},
new Movie{Title="Return of the Devil", Director="Michael", Genre=2, RunTime=80, ReleaseDate ="01/01/1998"},
new Movie{Title="Warriors", Director="Phil", Genre=3, RunTime=120, ReleaseDate ="01/01/1991"},
new Movie{Title="Love", Director="Kevin", Genre=4, RunTime=120, ReleaseDate ="01/01/1992"},
new Movie{Title="Live Forever", Director="Leonardo", Genre=5, RunTime=120, ReleaseDate ="01/01/1997"},
new Movie{Title="War", Director="Adams", Genre=6, RunTime=130, ReleaseDate ="01/01/2001"},
new Movie{Title="Crimes of the City", Director="Ricky", Genre=6, RunTime=130, ReleaseDate ="01/01/1995"},
new Movie{Title="Street Fighters", Director="Andrew", Genre=6, RunTime=130, ReleaseDate ="01/01/1995"},
new Movie{Title="Violence", Director="David", Genre=6, RunTime=130, ReleaseDate ="01/01/1998"},
new Movie{Title="College Days", Director="Clarke", Genre=4, RunTime=140, ReleaseDate ="01/01/1997"},

};
}


Query: Get all movies from generic movies collection.
var movies = GetMovies();
var query = from m in movies select m;

Query : Return a new projection containing Title and Genre.
var movies = GetMovies();
var query = from m in movies select new {m.Title, m.Genre};
or
var query = from m in movies select new {MovieTitle = m.Title, MovieGenre = m.Genre};

Query: Return all movies order by Title
var movies = GetMovies();
var query = from m in movies order by m.Title descending select m

Query: Adding a filter to a Linq query.
var movies = GetMovies();
var query = from m in movies where m.Genre=5 select m;

Query: Data Grouping
var movies = GetMovies();
var query = from m in movies group by m.Genre into g
            select new {Genre = g.key, Count = g.Count} 
            

Query : Linq Operators
var movies = GetMovies();
movies.Max(m=>m.RunTime)
movies.Min(m=>m.RunTim)
movies.Average(m=>m.RunTime)

Query: Linq Joins
var moveis = GetMovies();
var genres = GetGenres();

var query = from m in movies Join g in genres On m.Genre Equals g.ID
            select new {Title = m.Title, Genre = g.Name}
Query: Left Join
All movies from movies object irrespecitive of having a genre or not.

var m = from m in movies join g in generes on m.Genre equals g.ID into MovGen
              from MovGenJ in MovGen.DefaultIfEmpty()
             select new {Title = m.Title, Genre = g.Name}

Query: Paging using Linq

var query = (from m in movies Join g in generes On m.Genre Equals g.ID 
             select new {Title = m.Title, Genre = g.Name}).Skip(10).Take(10);
Query: For loop in Linq

var m = movies.ForEach(m =>m.Budget = GetMoviesBudget(m.ID))

Tuesday, May 10, 2011

What's new in VS2010



Web.Config Transformation


As we all know that Web.config in Dev environment is never same in Test and Prod environment. We have to replace couple of entries like Connection string etc. for Test and Prod.

VS2010 gives an excellent feature called as Web.Config Transformation to automate these changes. Let's see here how it is done.

1. Open Configuration Manager from Build menu.
2. Create a new Config file using Configuration Manager -> New
3. Lets name it as MyTransform.
4. Right click on the Web.Config file and select Add Config Transform. VS2010 will
create web.MyTransform.config file. This is the file where we will make our Prod entries.
5. Open the Web.Config file and add following entries.





6. Add the production entries in the web.MyTransform.config file as follows





7. For testing purpose, let's create an Application under Default Web Site on our local box. Let's assume this as Prod Url.
8. Now publish your Web Application to your Prod Url by Right click on Project and choose Publish.
9. Open the Physical path of the Prod Url and check the Web.Config file. You will find the "ProdBox" for the "ServerName" key in the appSettings section.

Thursday, May 5, 2011

ASP.NET MVC 3 Tools Update



This tools update will include following tooling improvement.

  1. Final release of EF 4.1.
  2. Built-in data scaffolding support
  3. New HTML5 project templates
  4. Intranet Project Template
  5. Newer versions of jQuery core, jQuery UI and jQuery Validation

Download

Tuesday, May 3, 2011

Breaking changes of Jquery 1.6



Case-mapping of data- attributes

In Jquery 1.5.2, an attribute of data-max-value="15" would create a data object of { max-value: 15 } but as of jQuery 1.6 it sets { maxValue: 15 }. It is done to match W3C HTML5 spec.

Handling of DOM properties and DOM attributes separatly
.prop() -
.removeProp() -
.attr() -

Properties represent the dynamic state of DOM, whereas Attributes represent the state of DOM information as retrieved from the document.
Ex: $(this).prop("checked") - returns current state of the checkbox.

Ajax
Bugs Fixed:

#6481: revert $.param should treat empty arrays/objects like empty strings
#7881: Make compatible with XHR 2
#8417: When posting AJAX and the data has “??” is formats it to jQuery?
#8744: .ajax() jsonp requests are not handled correctly when hitting timeout
#8884: jqXHR breaks names of custom header fields

Performance Improvement
.attr("alue");
.attr("name", "value")
.val() - get
.data()

boolean attributes

$(#checkbox).attr("checked","true"); - check it
$(#checkbox).attr("checked","false"); - Uncheck it

Bugs fixed
Bugs Fixed:

#1591: IE "Invalid Argument" $('table').attr('non-existent')
#3116: .attr does not work with SVG IDLs
#3786: removeAttr should use jQuery.props
#4283: .attr('checked') & XHTML 1.1 Strict
#4464: IE cannot get width attribute of detached IMG element
#4978: jQuery.prop missing cellpadding?
#5413: tag "img" width/height attribute is zero (IE)
#6562: using .attr() to set the ‘target’ attribute, with a node that has ID of 'target'
#6708: Opera has inconsistent result for usemap attribute value
#6823: Make .val(value) faster for common use case
#7472: $('form').attr('id') return DOM Element
#7485: Inconsistency between has [attribute] selector and attr() method
#7709: Permission denied to access property ‘nodeType’ from a non-chrome Firefox/3.5.15
#7996: Safari $('script').attr(‘event’); Bug
#8117: .removeAttr don’t works with select element’s size attribute
#8150: removeAttr issue in webkit, firefox
#8255: support for list attribute
#8418: set name parameter using attr() method in IE 7
#8457: attrHooks
#8570: .val method returning “on” for dynamically created radio buttons in ie9
#8699: .attr() returns -1 on missing attribute instead of undefined
#8772: Using .attr() to set input type 'range' causes script error in IE9
#8997: new attribute “form” (HTML5) is not supported, .attr(‘form’) not working properly
#9037: $('blah').attr('onclick') return event in Firefox

Event - Bugs fixed
#5884: live mouseenter/mouseleave events don’t fire as expected when nested
#6514: Mouseenter and mouseleave events not able to be triggered if bound by live
#6913: namespaced event bubbleing wrong
#6993: .bind() and .one() don’t allow a function as data
#7071: Accessing the ‘type’ property on VML elements fails on IE
#7883: .delegate (and .live) should accept false as the fn arg, like .bind
#8018: Unsafe access to frameElement causes error in crossdomain (i)frames
#8272: Exceptions in plain JS object event handlers swallowed by jQuery
#8712: Custom events don’t bubble up to window
#8732: Incorrect feature detect for IE9 focusin/focusout
#8753: jQuery 1.6: jQuery.Event contstructor to support setting properties
#8755: binding to beforeunload throws an error in IE6, 7, 8 on page unload
#8777: jQuery 1.6: undelegate() accepts custom namespaced events
#8788: Reorganize jQuery.event.trigger to use loop instead of recursion
#8790: Optimize non-attached events such as data events
#8803: jQuery.holdReady() method


Manipulation - Bugs fixed

#1954: val() returns innerHTML for button elements in IE
#6180: jQuery.clean should not touch script tags that are not of type text/javascript
#7623: Exception thrown in replaceWith
#7885: jQuery .offset doesn’t property works when current offset is float (which is possible in FireFox)
#8060: Setting checked to true on a disconnected checkbox does not carry over after attaching to DOM.
#8500: radios and checkboxes revert to default (HTML) state when wrapped in IE

Misc
Bugs Fixed:


#8203: Remove un-needed “someVar = null;”s
#8851: Wraps strings with double quotes in sources and tests
#8882: Tests: Update QUnit usage, replace id=main with id=qunit-fixture


Selector
:focus Selector

In jQuery 1.6 we now ensure that the :focus selector works properly across all browsers. You can use this selector to find the currently focused element on the page (such as a form input).

$("input:focus").addClass("active");

#3685: Selector fails for forms with an element named “name”
#4321: $(“#”) returns undefined
#8105: :focus selector filter


Support
Bugs Fixed:


#9028: IE8 crashes while loading 1.6rc1 if using body background image


Traversing

find(), closest(), and is() now all take DOM elements and jQuery objects
In jQuery 1.6 we’ve ensured that find(), closest(), and is() can all take DOM elements and jQuery objects as arguments. This gives you alternatives for filtering sets of elements based upon the passed-in elements.

// Only returns .test elements if they're inside of a div
$("div").find( $(".test") )

Bugs Fixed:

#2773: $.fn.is and $.fn.not should accept DOMelements and jQuery collections
#5712: Allow jQuery.fn.is to accept a function
#6912: $().add(selectElement) adds option children instead
#7369:
$('
ff
').closest('[attr]');
raises exception in all browsers
#8609: Result of .find("") is undefined

Reference : http://blog.jquery.com/2011/05/03/jquery-16-released/

Thursday, April 28, 2011

Impact of Content Type changes on existing Lists in SharePoint 2007

In real world, we come across of many business scenarios that force us to add/edit/remove some columns to our existing Lists. Sometimes these Lists are heavily populated with large amount of data and workflows running on them. As we all know we add columns to a SharePoint List using Content Types for reusability purpose. So changing the columns of a List means changing the Content Type associated with the List. In such a situation, several questions come to one's mind.

1. Can I simply add the new field references to my existing ContentType CAML and re-activate the feature ? Will the new fields be added to the existing Lists ? Will it impact the running workflows on the Lists ?

We all know for sure that the new fields will be part of a new List that we create after the change. But what about the existing Lists. Simply adding the new field references to the existing Content Type CAML will not reflect in the existing Lists. You need to add these field references programmatically inside a feature receiver by passing true to the Update() method of the Content Type. Here is the sample code snippet.


public override void FeatureActivated(SPFeatureReceiverProperties properties)
{
using (SPWeb web = ((SPSite)properties.Feature.Parent).OpenWeb())
{
SPContentType pcType = web.ContentTypes[new SPContentTypeId("GUID of the existing Content Type")];
SPField newField = web.Fields[new Guid("GUID of Field")];
SPFieldLink newFieldLink = new SPFieldLink(newField);
pcType.FieldLinks.Add(newFieldLink);
pcType.Update(true);
}
}


Any change in the Content Type should not impact the running workflows on the Lists.

When we remove fields from an existing Content Type and re-deploy it, the same columns would not be removed from the Lists that use the Content Type. Safety of the List Data is utmost important for SharePoint.

At the end, Don't forget to remove these field references inside feature deactivating event.

public override void FeatureDeactivating(SPFeatureReceiverProperties properties)
{
using (SPWeb web = ((SPSite)properties.Feature.Parent).OpenWeb())
{
SPContentType pcType = web.ContentTypes[new SPContentTypeId("GUID of the existing Content Type")];
SPField newField = web.Fields[new Guid("GUID of Field")];
if (pcType.Fields.ContainsField(newField .Title))
pcType.FieldLinks.Delete(new Guid(GUID of Field));
pcType.Update(true);
}
}


Some facts related to Content Type -
If you delete the content type associated to a List, then it won't delete the columns in the List. They would be still exist as local columns. if you want to remove them from your List, then you have to delete them manually or programmatically.

What's New in C# 4.0

1) Optional Parameters


public class Order
{
//Old way
public int Purchase(Product product, Customer customer, bool isResale, string discountCode)
{

}
// New way
public int Purchase(Product product, Customer customer, bool isResale = false, string discountCode = string.Empty)
{
}
}
public class Program
{
static void Main(string[] args)
{
Order newOrder = new Order();
Product item = new Product { ItemCode = "A8901", Price = 50, Qty = 5};
Customer customer = new Customer();
customer.UserName = "R887663";
customer.PreferredCustomer = true;
newOrder.Purchase(item, customer);
}
}


2. Named Parameters


public class Program
{
static void Main(string[] args)
{
Order newOrder = new Order();
Product item = new Product { ItemCode = "A8901", Price = 50, Qty = 5};
Customer customer = new Customer();
customer.UserName = "R887663";
customer.PreferredCustomer = true;
newOrder.Purchase(item, customer, discountCode: 76883987);
}
}

3. Use of dynamic keyword


static class DynamicDemo
{
public static void Execute()
{
var person = new Person { Name = "Alex" };
var company = new Company { Name = "Microsoft" };

DoSomething(person);
DoSomething(company);
}

static void DoSomething(dynamic item)
{
Console.WriteLine(item.Name);
}
}

class Person
{
public string Name { get; set; }
}

class Company
{
public string Name { get; set; }
}



4. Use of DynamicObject


class DynamicObjectSimpleDemo : DynamicObject
{
private Dictionary members = new Dictionary();

public override bool TryGetMember(GetMemberBinder binder, out object result)
{
return this.members.TryGetValue(binder.Name, out result);
}

public override bool TrySetMember(SetMemberBinder binder, object value)
{
this.members[binder.Name] = value;
return true;
}
}

public class DynamicObjectXDemo : DynamicObject
{
private XElement element;

public DynamicObjectXDemo (XElement element)
{
this.element = element;
}

public override bool TryGetMember(GetMemberBinder binder, out object result)
{
result = this.element.Attribute(binder.Name).Value;
return true;
}

public override bool TrySetMember(SetMemberBinder binder, object value)
{
this.element.SetAttributeValue(binder.Name, value);
return true;
}
}

class program
{
static void main(string[] args)
{
dynamic sample = new DynamicObjectSimpleDemo();
sample.Fname = "Alex";
sample.LName = "Palle";

var xml = XElement.Load("Clients.xml").Elements().Select(x => new DynamicObjectXDemo(x));

foreach (dynamic item in xml)
{
Console.WriteLine(item.FName+ " " + item.LName);
}
}
}

//Clients.xml









What's New in ASP.NET 4.0

1. In .NET Framework 4.0, the major configuration elements are moved to machine.config and applications now inherits these settings.
Sample of ASP.NET 4 Web.Config file









2. Output caching in ASP.NET 4 enables you to configure one or more custom output- cache providers. Output-cache providers can use any storage mechanism i.e. local or remote disks, cloud, distributed cache engine etc. to persist HTML content.
Example of specifying a different output-cahce provider for web page or web user control.


<%@ OutputCache Duration="60" VaryByParam="None"
providerName="DiskCache" %>


3. Some ASP.NET applications need to load large amount of data during initilization of the application before serving the first request. Prior to Asp.NET 4.0, we achieve the compilation of the application before the first request using the command Aspnet_compiler -v /MyWebSite. In Asp.NET 4.0, auto-start feature is available when ASP.NET 4 runs on IIS 7.5 on Windows Server 2008 R2.

You need to set following configuration in the ApplicationHost.config file.







If your application pool containing multiple applications, you can auto-start individual applications by setting the following configuration in applicationHost.config file.






The auto-start feature enables you to

  1. Start up the Application pool.
  2. Initialization of the Application
  3. It temporarily stops processing any http request till the initilization process is over.


4. The ASP.NET Redirect method results an extra round trip while doing a temporary redirect to an URL. ASP.NET 4.0 adds a new Helper method RedirectPermanent() that saves an unnecessary round trip.
While the Redirect method returns HTTP 302(Found) response, the RedirectPermanent() method issues HTTP 301(Permanent) response.

5. In Asp.net, The out of process Session State involves serialized session date sent to remote storage. It becomes a performance bottleneck if the data involved is large. The ASP.NET 4.0 Session State Compression feature helps to reduce the size of the data by compressing the Session State using GZipStream class. The Applications that have spare CPU cycles on the Web Server can achieve substantial performance improvement by using this feature.

You can set this option using the new compressionEnabled attribute of the sessionState element in the configuration file.

6. ASP.NET 4.0 allows you to configure the application URL path, query string length and invalid characters that are not allowed in the application url. You can configure them as follows.





7. The ASP.NET 4.0 System.Runtime.Caching API provides an uniform caching technique for all .NET applications (Web, Windows Form). It provides abstract types for custom cache implementation and a concrete in-memory object cache class called MemoryCache.

8. In ASP.NET 4, you can create custom encoding routines for the following common text-encoding tasks:

  • HTML encoding.
  • URL encoding.
  • HTML attribute encoding.
  • Encoding outbound HTTP headers.


Configure the custom encoding routines as follows:




9. CDN base Ajax and Jquery loading to ASP.NET 4.0 Applications.






[assembly: WebResource("Example.js", "application/x-javascript", CdnPath ="http://contoso.com/app/site/Example.js")]



10. 2 new properties are added to the Page class i.e. MetaKeywords, MetaDescription that helps set meta tags for search engine submission. The html rendered on the browser by these 2 properties is as follows:


<html>
<head>
<meta name="keywords" content="keyword1, keyword2"/>
<meta name="description" content="description"/>
</head>
<html>


11. A New property ViewStateMode is added to Control class. Setting ViewStateMode=false of the Control class disables viewstate for all the controls on the page. You can use ViewStateMode property of indiviual control to enable view state explicitly.

12. ASP.NET MVC way of routing in ASP.NET 4 Web Forms.

13. We use a Control's Client ID property to access that control in client script. Prior to ASP.NET 4.0, the Client ID is generated automatically by ASP.NET engine and sometimes it is difficult to predict the Client ID of a control to use in client script. In ASP.NET 4.0, you can specify how it can be generated by using ClientIDMode property at Page level or control level. It has following values:

Auto - It provides the same behaviour ASP.NET was providing prior to ASP.NET 4.0

Static - Instead of automatically generating Client ID, it sets the ID of the control as Client ID.

Predictable - For a Data Bound control, You can control how the ID of each instance of the control would be created by using ClientIDRowSuffix property. The value of this property will be appended to the Client ID property of each instance of the control.

Inherit - Inherit the ClientIDMode property of the container control to generate the Client ID of the control. If the control doesn't have a container control then it uses the ClientIDMode property of the Page.

The default mode for a site or page is - Predictable
The default mode for a control is - inherits

The following example shows how to set the default ClientIDMode for a site in the Web.config file.





The following example shows how to set the default ClientIDMode for a page in the @ Page directive.


<%@ Page Language="C#" CodeFile="Default.aspx.cs"

Inherits="_Default" ClientIDMode="Static" %>


14. Persisting row selection in Data Controls - Rows selected in Pages will be persisted across pages. When you select a row 3 on Page1 and move to Page8. If you go back to Page1, you will see row3 as selected. To achieve this, use PersistedSelection property of the Data Control.






15. Filtering date with the QueryExtender control. The Query Extender control can be added to EntityDataSource or LinqDataSource to filter the data. The QueryExtender has following filter options-


ContextTypeName="AdventureWorksDataContext" EntityTypeName=""
TableName="Products" >



SearchExpression -
RangeExpression-
PropertyExpression-
OrberByExpression-
CustomExpression-


<html>
<head runat="server">
<title>Filter Demo</title>
</head>
<body>
<form id="form1" runat="server">
Search:<asp:TextBox ID="SearchTextBox" runat="server" />
<p>

Make More:<asp:CheckBox ID="MakeCheckBox" runat="server" />
<p>
From:<asp:TextBox ID="FromTextBox" runat="server" ></asp:TextBox>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
To:<asp:TextBox ID="ToTextBox" runat="server" ></asp:TextBox>
</p>
<p>
<asp:Button ID="Button1" runat="server" Text="Search" />
</p>
<asp:LinqDataSource ID="LinqDataSource1"
ContextTypeName="FilterDemo.AdventureWorksDataContext"
TableName="Products" runat="server">
</asp:LinqDataSource>
<asp:QueryExtender runat="server" TargetControlID="LinqDataSource1">

<asp:SearchExpression SearchType="StartsWith" DataFields="Name" >
<asp:ControlParameter ControlID="SearchTextBox" />
</asp:SearchExpression>

<asp:RangeExpression DataField="ReorderPoint" MinType="Inclusive" MaxType="Inclusive">
<asp:ControlParameter ControlID="FromTextBox" />
<asp:ControlParameter ControlID="ToTextBox" />
</asp:RangeExpression>

<asp:PropertyExpression>
<asp:ControlParameter ControlID="MakeCheckBox" Name="MakeFlag" />
</asp:PropertyExpression>
</asp:QueryExtender>

<asp:GridView ID="GridView1" runat="server"
DataSourceID="LinqDataSource1" AllowPaging="True"
DataKeyNames="ProductID>
</asp:GridView>
</form>

</body>
</head>
</html>

Tuesday, April 19, 2011

Using WebGrid in ASP.NET MVC3


@model IEnumerable

@{
ViewBag.Title = "Employee Grid";
}

@{
var grid = new WebGrid(source: Model, defaultSort:"Name", rowsPerPage:3);
}

Employee Grid



@grid.GetHtml(columns: grid.Columns(grid.Column("Id"), grid.Column("Name"), grid.Column("JoiningDate"), grid.Column("PAN")))

MVC Application Execution Process (C#)


  1. When Receive first request for the application-
    In the Global.asax file, Route objects are added to the RouteTable object
  2. Perform routing -
    The UrlRoutingModule
    module uses the first matching Route object in the RouteTable
    collection to create the RouteData object, which it then uses
    to create a RequestContext (IHttpContext) object.
  3. Create MVC request handler -
    The MvcRouteHandler object creates an instance of the MvcHandler class and passes it the RequestContext instance.
  4. Create controller -
    The MvcHandler object uses the RequestContext instance to identify the IControllerFactory object (typically an instance of the DefaultControllerFactory class) to create the controller instance with.
  5. Execute controller -
    The MvcHandler instance
    calls the controller s Execute method.
  6. Invoke action -
    Most controllers inherit from the Controller base class. For controllers that do so, the ControllerActionInvoker object that is associated with the controller determines which action method of the controller class to call, and
    then calls that method.
  7. Execute result -
    A typical action method might receive user input, prepare the appropriate response data, and then execute the result by returning a result type. The built-in result types that can be executed include the following: ViewResult (which
    renders a view and is the most-often used result type), RedirectToRouteResult,
    RedirectResult
    , ContentResult, JsonResult, and
    EmptyResult
    .

Friday, April 15, 2011

Extract WSP from SharePoint Solution Store


using Microsoft.SharePoint;
using Microsoft.SharePoint.Administration;

static void Main(string[] args)
{
const string extractingTo = "e:\\Solutions\\";
SPSolutionCollection solutions = SPFarm.Local.Solutions;
foreach (SPSolution solution in solutions)
{
Console.WriteLine("Extracting " + solution.Name);
SPPersistedFile wspFile = solution.SolutionFile;
wspFile.SaveAs(extractingTo + solution.Name);
}
}

System.Data.SqlClient.SqlException while installing SPJob during Feature activation

Recently we came across following exception while installing SPJob during Feature installation. System.Data.SqlClient.SqlException: The EXECUTE permission was denied on the object 'proc_putObject', database 'SharePoint_Config', schema 'dbo'.

Reason: The scope of the feature was "Web". In fact the same exception will occure if you define the scope of the feature as "Site".

Solution: Define the scope of the feature as "Web Application".

Monday, April 11, 2011

Edit Header/Footer of Word Document programmatically using Office Open XML

Scenario- My Client wants to publish policy document(Word Document) to multiple departments with department specific header and footer.

Design-
System.IO.Packing API provides strongly typed classes to manipulate office documents that adhere to office open XML file format specification. An open XML document like Word Document is stored as a package. The package has multiple parts like main document, header, footer etc. with relationship between them. The header part is included in the document by header reference tag. Changing the header information of a Word Document is to delete the existing header part and add a new header part.

Solution-

public SPFile ProcessHeaderFooter(string targetFilePath, string department)
{
string headerInfo = GetHeaderInfo(department);
string footerInfo = GetFooterInfo(department);

Stream headerStream = new MemoryStream(System.Text.Encoding.UTF8.GetBytes(headerContent));
Stream footerStream = new MemoryStream(System.Text.Encoding.UTF8.GetBytes (footerContent));

SPWeb web = SpContext.Current.Web;
SPFile targetFile = web.GetFile(targetFilePath);
MemoryStream fileStream = new MemoryStream();
fileStream.Write(targetFile.OpenBinary(), 0, (int)targetFile.TotalLength);
AddHeader(headerStream, fileStream);
AddFooter(footerStream, fileStream);
targetFile.SaveBinary(fileStream);
fileStream.Close();
return targetFile;
}

public void AddHeader(Stream headerContent, Stream fileContent)
{
const string documentRelationshipType = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument";
const string wordmlNamespace = "http://schemas.openxmlformats.org/wordprocessingml/2006/main";
const string headerContentType = "application/vnd.openxmlformats-officedocument.wordprocessingml.header+xml";
const string headerRelationshipType = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/header";
const string relationshipNamespace = "http://schemas.openxmlformats.org/officeDocument/2006/relationships";
PackagePart documentPart = null;
using (Package wdPackage = Package.Open(fileContent, FileMode.Open, FileAccess.ReadWrite))
{
// Get the main document part (document.xml).
foreach (System.IO.Packaging.PackageRelationship relationship in wdPackage.GetRelationshipsByType(documentRelationshipType))
{
Uri documentUri = PackUriHelper.ResolvePartUri(new Uri("/", UriKind.Relative), relationship.TargetUri);
documentPart = wdPackage.GetPart(documentUri);
// There is only one officeDocument.
break;
}

Uri uriHeader = new Uri("/word/header1.xml", UriKind.Relative);

if (wdPackage.PartExists(uriHeader))
{
wdPackage.DeletePart(uriHeader);
}

// Create the header part.
PackagePart headerPart = wdPackage.CreatePart(uriHeader, headerContentType);
XmlDocument headerDoc = new XmlDocument();
headerContent.Position = 0;
headerDoc.Load(headerContent);

// Write the header out to its part.
headerDoc.Save(headerPart.GetStream());

// Create the document's relationship to the new part.
PackageRelationship rel = documentPart.CreateRelationship(uriHeader, TargetMode.Internal, headerRelationshipType);
string relID = rel.Id;

// Manage namespaces to perform Xml XPath queries.
NameTable nt = new NameTable();
XmlNamespaceManager nsManager = new XmlNamespaceManager(nt);
nsManager.AddNamespace("w", wordmlNamespace);

// Get the document part from the package.
// Load the XML in the part into an XmlDocument instance.
XmlDocument xdoc = new XmlDocument(nt);
xdoc.Load(documentPart.GetStream());

// Find the node containing the document layout.
XmlNode targetNode = xdoc.SelectSingleNode("//w:sectPr", nsManager);
if (targetNode != null)
{
// Delete any existing references to headers.
XmlNodeList headerNodes = targetNode.SelectNodes("./w:headerReference", nsManager);
foreach (System.Xml.XmlNode headerNode in headerNodes)
{
targetNode.RemoveChild(headerNode);
}

// Create the new header reference node.
XmlElement node = xdoc.CreateElement("w:headerReference", wordmlNamespace);
XmlAttribute attr = node.Attributes.Append(xdoc.CreateAttribute("r:id", relationshipNamespace));
attr.Value = relID;
node.Attributes.Append(attr);
targetNode.InsertBefore(node, targetNode.FirstChild);
}

// Save the document XML back to its part.
xdoc.Save(documentPart.GetStream(FileMode.Create, FileAccess.Write));
}
}


public void AddFooter(Stream footerContent, Stream fileContent)
{
const string documentRelationshipType = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument";
const string wordmlNamespace = "http://schemas.openxmlformats.org/wordprocessingml/2006/main";
const string footerContentType = "application/vnd.openxmlformats-officedocument.wordprocessingml.footer+xml";
const string footerRelationshipType = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/footer";
const string relationshipNamespace = "http://schemas.openxmlformats.org/officeDocument/2006/relationships";
PackagePart documentPart = null;
using (Package wdPackage = Package.Open(fileContent, FileMode.Open, FileAccess.ReadWrite))
{
// Get the main document part (document.xml).
foreach (System.IO.Packaging.PackageRelationship relationship in wdPackage.GetRelationshipsByType(documentRelationshipType))
{
Uri documentUri = PackUriHelper.ResolvePartUri(new Uri("/", UriKind.Relative), relationship.TargetUri);
documentPart = wdPackage.GetPart(documentUri);
// There is only one officeDocument.
break;
}

Uri uriFooter = new Uri("/word/footer1.xml", UriKind.Relative);
if (wdPackage.PartExists(uriFooter))
{
// Although you can delete the relationship
// to the existing node, the next time you save
// the document after making changes, Word
// will delete the relationship.
wdPackage.DeletePart(uriFooter);
}
// Create the footer part.
PackagePart footerPart = wdPackage.CreatePart(uriFooter, footerContentType);

XmlDocument footerDoc = new XmlDocument();
footerContent.Position = 0;
footerDoc.Load(footerContent);
// Write the footer out to its part.
footerDoc.Save(footerPart.GetStream());
// Create the document's relationship to the new part.
PackageRelationship rel = documentPart.CreateRelationship(uriFooter, TargetMode.Internal, footerRelationshipType);
string relID = rel.Id;

// Manage namespaces to perform Xml XPath queries.
NameTable nt = new NameTable();
XmlNamespaceManager nsManager = new XmlNamespaceManager(nt);
nsManager.AddNamespace("w", wordmlNamespace);

// Get the document part from the package.
// Load the XML in the part into an XmlDocument instance.
XmlDocument xdoc = new XmlDocument(nt);
xdoc.Load(documentPart.GetStream());

// Find the node containing the document layout.
XmlNode targetNode = xdoc.SelectSingleNode("//w:sectPr", nsManager);
if (targetNode != null)
{
// Delete any existing references to footers.
XmlNodeList footerNodes = targetNode.SelectNodes("./w:footerReference", nsManager);
foreach (System.Xml.XmlNode footerNode in footerNodes)
{
targetNode.RemoveChild(footerNode);
}

// Create the new footer reference node.
XmlElement node = xdoc.CreateElement("w:footerReference", wordmlNamespace);
XmlAttribute attr = node.Attributes.Append(xdoc.CreateAttribute("r:id", relationshipNamespace));
attr.Value = relID;
node.Attributes.Append(attr);
targetNode.InsertBefore(node, targetNode.FirstChild);
}

// Save the document XML back to its part.
xdoc.Save(documentPart.GetStream(FileMode.Create, FileAccess.Write));
}
}


References
http://msdn.microsoft.com/en-us/library/bb491088(v=office.12).aspx