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