Friday, June 8, 2012

Implemention of the Repository and Unit of Work Patterns in an ASP.NET MVC Application

Today, I'm posting about implementing unit of work patterns repository in an Asp.net mvc application

I believe Ninject repository patterns and Unit of Work repository patterns are the best repository patterns in asp.net mvc application

The repository patterns are an abstarction layer. Implementing these patterns perform between the data access layer and the business logic layer of an application. And The repository is very useful in automated unit testing or test-driven developement(TDD).

The diagram image below explains where repository patterns perform in an application

Reference: Tom Dykstra blog

Let's see example of :

create a sample book object repository class with Generic Repoistory class

In DAL folder or service folder or repository folder, create this class file.

1. this code should be in interface folder ( without UnitofWork class)

   1:  using System; 
   2:  using System.Collections.Generic; 
   3:  using System.Linq; 
   4:  using System.Web; 
   5:  using MyApplication.Models; 
   6:   
   7:  namespace MyApplication.DAL 
   8:  { 
   9:      public interface IBookRepository : IDisposable 
  10:      { 
  11:          IEnumerable<Student> GetBooks(); 
  12:          Book GetBookByID(int bookId); 
  13:          void InsertBook(Book book); 
  14:          void DeleteBook(int bookID); 
  15:          void UpdateBook(Book book); 
  16:          void Save(); 
  17:      } 
  18:  }

2. this code should be in repository folder ( without UnitofWork class)

   1:  using System; 
   2:  using System.Collections.Generic; 
   3:  using System.Linq; 
   4:  using System.Data; 
   5:  using MyApplication.Models; 
   6:   
   7:  namespace MyApplication.DAL 
   8:  { 
   9:      public class BookRepository : IBookRepository, IDisposable 
  10:      { 
  11:          private SchoolContext context; 
  12:   
  13:          public BookRepository(SchoolContext context) 
  14:          { 
  15:              this.context = context; 
  16:          } 
  17:   
  18:          public IEnumerable<Book> GetBooks() 
  19:          { 
  20:              return context.Books.ToList(); 
  21:          } 
  22:   
  23:          public Book GetBookByID(int id) 
  24:          { 
  25:              return context.Books.Find(id); 
  26:          } 
  27:   
  28:          public void InsertBook(Book book) 
  29:          { 
  30:              context.Books.Add(book); 
  31:          } 
  32:   
  33:          public void DeleteBook(int bookID) 
  34:          { 
  35:              Book book = context.Books.Find(bookID); 
  36:              context.Books.Remove(book); 
  37:          } 
  38:   
  39:          public void UpdateBook(Book book) 
  40:          { 
  41:              context.Entry(book).State = EntityState.Modified; 
  42:          } 
  43:   
  44:          public void Save() 
  45:          { 
  46:              context.SaveChanges(); 
  47:          } 
  48:   
  49:          private bool disposed = false; 
  50:   
  51:          protected virtual void Dispose(bool disposing) 
  52:          { 
  53:              if (!this.disposed) 
  54:              { 
  55:                  if (disposing) 
  56:                  { 
  57:                      context.Dispose(); 
  58:                  } 
  59:              } 
  60:              this.disposed = true; 
  61:          } 
  62:   
  63:          public void Dispose() 
  64:          { 
  65:              Dispose(true); 
  66:              GC.SuppressFinalize(this); 
  67:          } 
  68:      } 
  69:  }

Then, the following codes show how to use the repository in the book controller.

Using book respoitory in book controller ( without UnitofWork class)

   1:  using System; 
   2:  using System.Collections.Generic; 
   3:  using System.Data; 
   4:  using System.Data.Entity; 
   5:  using System.Linq; 
   6:  using System.Web; 
   7:  using System.Web.Mvc; 
   8:  using MyApplication.Models; 
   9:  using MyApplication.DAL; 
  10:  using PagedList; 
  11:   
  12:  namespace MyApplication.Controllers 
  13:  { 
  14:      public class BookController : Controller 
  15:      { 
  16:          private IBookRepository bookRepository; 
  17:   
  18:   
  19:          public BookController() 
  20:          { 
  21:              this.bookRepository = new BookRepository(new BookStoreContext()); 
  22:          } 
  23:   
  24:          public StudentController(IBookRepository bookRepository) 
  25:          { 
  26:              this.bookRepository = bookRepository; 
  27:          } 
  28:   
  29:   
  30:          // 
  31:          // GET: /Book/ 
  32:   
  33:          public ViewResult Index(string sortOrder, string currentFilter, string searchString, int? page) 
  34:          { 
  35:              ViewBag.CurrentSort = sortOrder; 
  36:              ViewBag.NameSortParm = String.IsNullOrEmpty(sortOrder) ? "Name desc" : ""; 
  37:              ViewBag.DateSortParm = sortOrder == "Date" ? "Date desc" : "Date"; 
  38:   
  39:              if (Request.HttpMethod == "GET") 
  40:              { 
  41:                  searchString = currentFilter; 
  42:              } 
  43:              else 
  44:              { 
  45:                  page = 1; 
  46:              } 
  47:              ViewBag.CurrentFilter = searchString; 
  48:               
  49:              var books = from s in bookRepository.GetBooks() 
  50:                             select s; 
  51:              if (!String.IsNullOrEmpty(searchString)) 
  52:              { 
  53:                  books = books.Where(s => s.Name.ToUpper().Contains(searchString.ToUpper()) 
  54:                                         || s.AutherName.ToUpper().Contains(searchString.ToUpper())); 
  55:              } 
  56:              switch (sortOrder) 
  57:              { 
  58:                  case "Name desc": 
  59:                      books = books.OrderByDescending(s => s.Name); 
  60:                      break; 
  61:                  case "Date": 
  62:                      books = books.OrderBy(s => s.PublishedDate); 
  63:                      break; 
  64:                  case "Date desc": 
  65:                      books = books.OrderByDescending(s => s.PublishedDate); 
  66:                      break; 
  67:                  default: 
  68:                      books = books.OrderBy(s => s.Name); 
  69:                      break; 
  70:              } 
  71:   
  72:              int pageSize = 3; 
  73:              int pageNumber = (page ?? 1); 
  74:              return View(books.ToPagedList(pageNumber, pageSize)); 
  75:          } 
  76:   
  77:   
  78:          // 
  79:          // GET: /Book/Details/5 
  80:   
  81:          public ViewResult Details(int id) 
  82:          { 
  83:              Book book = bookRepository.GetBookByID(id); 
  84:              return View(book); 
  85:          } 
  86:   
  87:          // 
  88:          // GET: /Book/Create 
  89:   
  90:          public ActionResult Create() 
  91:          { 
  92:              return View(); 
  93:          } 
  94:   
  95:          // 
  96:          // POST: /Book/Create 
  97:   
  98:          [HttpPost] 
  99:          public ActionResult Create(Book book) 
 100:          { 
 101:              try 
 102:              { 
 103:                  if (ModelState.IsValid) 
 104:                  { 
 105:                      BookRepository.InsertBook(book); 
 106:                      bookRepository.Save(); 
 107:                      return RedirectToAction("Index"); 
 108:                  } 
 109:              } 
 110:              catch (DataException) 
 111:              { 
 112:                  //Log the error (add a variable name after DataException) 
 113:                  ModelState.AddModelError("", "Unable to save changes. Try again, and if the problem persists see your system administrator."); 
 114:              } 
 115:              return View(book); 
 116:          } 
 117:   
 118:          // 
 119:          // GET: /Book/Edit/5 
 120:   
 121:          public ActionResult Edit(int id) 
 122:          { 
 123:              Book book = bookRepository.GetBookByID(id); 
 124:              return View(book); 
 125:          } 
 126:   
 127:          // 
 128:          // POST: /Book/Edit/5 
 129:   
 130:          [HttpPost] 
 131:          public ActionResult Edit(Book book) 
 132:          { 
 133:              try 
 134:              { 
 135:                  if (ModelState.IsValid) 
 136:                  { 
 137:                      bookRepository.UpdateBook(book); 
 138:                      bookRepository.Save(); 
 139:                      return RedirectToAction("Index"); 
 140:                  } 
 141:              } 
 142:              catch (DataException) 
 143:              { 
 144:                  //Log the error (add a variable name after DataException) 
 145:                  ModelState.AddModelError("", "Unable to save changes. Try again, and if the problem persists see your system administrator."); 
 146:              } 
 147:              return View(book); 
 148:          } 
 149:   
 150:          
 151:      // 
 152:          // GET: /Book/Delete/5 
 153:   
 154:          public ActionResult Delete(int id, bool? saveChangesError) 
 155:          { 
 156:              if (saveChangesError.GetValueOrDefault()) 
 157:              { 
 158:                  ViewBag.ErrorMessage = "Unable to save changes. Try again, and if the problem persists see your system administrator."; 
 159:              } 
 160:              Book book = bookRepository.GetBookByID(id); 
 161:              return View(book); 
 162:          } 
 163:   
 164:   
 165:          // 
 166:          // POST: /Book/Delete/5 
 167:   
 168:          [HttpPost, ActionName("Delete")] 
 169:          public ActionResult DeleteConfirmed(int id) 
 170:          { 
 171:              try 
 172:              { 
 173:                  Book book = bookRepository.GetBookByID(id); 
 174:                  bookRepository.DeleteBook(id); 
 175:                  bookRepository.Save(); 
 176:              } 
 177:              catch (DataException) 
 178:              { 
 179:                  //Log the error (add a variable name after DataException) 
 180:                  return RedirectToAction("Delete", 
 181:                      new System.Web.Routing.RouteValueDictionary {  
 182:                  { "id", id },  
 183:                  { "saveChangesError", true } }); 
 184:              } 
 185:              return RedirectToAction("Index"); 
 186:          } 
 187:     
 188:   
 189:          protected override void Dispose(bool disposing) 
 190:          { 
 191:              BookRepository.Dispose(); 
 192:              base.Dispose(disposing); 
 193:          } 
 194:      } 
 195:  }
------------------------- End (Without UnitofWork repository) ------------------

In the CRUD methods, the repository is now called instead of the entity model context ( I've assumed that you are familiar with entity edmx model).

Creating a repository class for each entity could result in a lot of redundant code. If you look up IBookRepository class and BookRepository class, you may think this repository is wasting the time writing all (GetbyId, InsertBook, updateBook, etc ..)

In this case, you need to use Generic repository class which redundants these functions (GetbyId, InsertBook, updateBook, etc ..) don't need to write every object respositorys that you create. You only need to write them once in the generic repoistory class. Then, all the other entity object repository can inheritances from generic repository class.

Here is an example why the generic repository should use:

Suppose you have to update two different entities that part of the same transaction. If each entity uses a separate database context instance, One might success and the other might fail. So, one way to minimize the redundant code and to ensure all repositories use the same database context are to use a unit of work class with Generic repository class.

The following codes are shown how to create generic repository class.

   1:  using System; 
   2:  using System.Collections.Generic; 
   3:  using System.Linq; 
   4:  using System.Data; 
   5:  using System.Data.Entity; 
   6:  using MyApplication.Models; 
   7:  using System.Linq.Expressions; 
   8:   
   9:  namespace MyApplication.DAL 
  10:  { 
  11:      public class GenericRepository<TEntity> where TEntity : class 
  12:      { 
  13:          internal SchoolContext context; 
  14:          internal DbSet<TEntity> dbSet; 
  15:   
  16:          public GenericRepository(SchoolContext context) 
  17:          { 
  18:              this.context = context; 
  19:              this.dbSet = context.Set<TEntity>(); 
  20:          } 
  21:   
  22:          public virtual IEnumerable<TEntity> Get( 
  23:              Expression<Func<TEntity, bool>> filter = null, 
  24:              Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null, 
  25:              string includeProperties = "") 
  26:          { 
  27:              IQueryable<TEntity> query = dbSet; 
  28:   
  29:              if (filter != null) 
  30:              { 
  31:                  query = query.Where(filter); 
  32:              } 
  33:   
  34:              foreach (var includeProperty in includeProperties.Split 
  35:                  (new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries)) 
  36:              { 
  37:                  query = query.Include(includeProperty); 
  38:              } 
  39:   
  40:              if (orderBy != null) 
  41:              { 
  42:                  return orderBy(query).ToList(); 
  43:              } 
  44:              else 
  45:              { 
  46:                  return query.ToList(); 
  47:              } 
  48:          } 
  49:   
  50:          public virtual TEntity GetByID(object id) 
  51:          { 
  52:              return dbSet.Find(id); 
  53:          } 
  54:   
  55:          public virtual void Insert(TEntity entity) 
  56:          { 
  57:              dbSet.Add(entity); 
  58:          } 
  59:   
  60:          public virtual void Delete(object id) 
  61:          { 
  62:              TEntity entityToDelete = dbSet.Find(id); 
  63:              Delete(entityToDelete); 
  64:          } 
  65:   
  66:          public virtual void Delete(TEntity entityToDelete) 
  67:          { 
  68:              if (context.Entry(entityToDelete).State == EntityState.Detached) 
  69:              { 
  70:                  dbSet.Attach(entityToDelete); 
  71:              } 
  72:              dbSet.Remove(entityToDelete); 
  73:          } 
  74:   
  75:          public virtual void Update(TEntity entityToUpdate) 
  76:          { 
  77:              dbSet.Attach(entityToUpdate); 
  78:              context.Entry(entityToUpdate).State = EntityState.Modified; 
  79:          } 
  80:      } 
  81:  }

I assume you notice that "Expression> filter" and "Func, IOrderedQueryable> orderBy" in the Get in the generic repository class.

   1:  Expression<Func<TEntity, bool>>

It means the caller will provide a lambda expression based on the TEntity type, and this expression returns a Boolean value. For example, if the repository is instantiated for the Book entity type, the code in the calling method might specify book => book.Name == "Skyfall" for the filter parameter.

   1:  Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy

It means the caller will provide a lambda expression. And the input to the expression is an IQueryable object for the TEntity type. The expression returns an ordered version of that IQueryable object. For example, if the repository is instantiated for the Student entity type, the code in the calling method might specify m => m.OrderBy(book => book.Name) for the orderBy parameter.

Creating Unit of Work class with generic repository class

In DAL folder, replace all the entity types repository class ( E.g BookRepository, CustomerRepoistory ) with this UnitofWork class and generic repository class

   1:  using System; 
   2:  using MyApplication.Models; 
   3:   
   4:  namespace MyApplication.DAL 
   5:  { 
   6:      public class UnitOfWork : IDisposable 
   7:      { 
   8:          private BookStoreContext context = new BookStoreContext(); 
   9:          private GenericRepository<Book> bookRepository; 
  10:          private GenericRepository<Customer> customerRepository; 
  11:   
  12:          public GenericRepository<Book> BookRepository 
  13:          { 
  14:              get 
  15:              { 
  16:   
  17:                  if (this.bookRepository == null) 
  18:                  { 
  19:                      this.bookRepository = new GenericRepository<Book>(context); 
  20:                  } 
  21:                  return bookRepository; 
  22:              } 
  23:          } 
  24:   
  25:          public GenericRepository<Customer> CustomerRepository 
  26:          { 
  27:              get 
  28:              { 
  29:   
  30:                  if (this.customerRepository == null) 
  31:                  { 
  32:                      this.customerRepository = new GenericRepository<Customer>(context); 
  33:                  } 
  34:                  return customerRepository; 
  35:              } 
  36:          } 
  37:   
  38:          public void Save() 
  39:          { 
  40:              context.SaveChanges(); 
  41:          } 
  42:   
  43:          private bool disposed = false; 
  44:   
  45:          protected virtual void Dispose(bool disposing) 
  46:          { 
  47:              if (!this.disposed) 
  48:              { 
  49:                  if (disposing) 
  50:                  { 
  51:                      context.Dispose(); 
  52:                  } 
  53:              } 
  54:              this.disposed = true; 
  55:          } 
  56:   
  57:          public void Dispose() 
  58:          { 
  59:              Dispose(true); 
  60:              GC.SuppressFinalize(this); 
  61:          } 
  62:      } 
  63:  }
  64:   
  65:   
  66:   
  67:  <h3>Creating CustomerController using with UnitofWork class</h3>
  68:   
  69:  using System; 
  70:  using System.Collections.Generic; 
  71:  using System.Data; 
  72:  using System.Data.Entity; 
  73:  using System.Linq; 
  74:  using System.Web; 
  75:  using System.Web.Mvc; 
  76:  using MyApplicaiton.Models; 
  77:  using MyApplicaiton.DAL; 
  78:   
  79:  namespace MyApplicaiton.Controllers 
  80:  {  
  81:      public class CustomerController : Controller 
  82:      { 
  83:          private UnitOfWork unitOfWork = new UnitOfWork(); 
  84:   
  85:          // 
  86:          // GET: /Customer/ 
  87:   
  88:          public ViewResult Index() 
  89:          { 
  90:              var customers = unitOfWork.CustomerRepository.Get(includeProperties: "Department"); 
  91:              return View(customers.ToList()); 
  92:          } 
  93:   
  94:          // 
  95:          // GET: /Customer/Details/5 
  96:   
  97:          public ViewResult Details(int id) 
  98:          { 
  99:              Customer customer = unitOfWork.CustomerRepository.GetByID(id); 
 100:              return View(customer); 
 101:          } 
 102:   
 103:          // 
 104:          // GET: /Customer/Create 
 105:   
 106:          public ActionResult Create() 
 107:          { 
 108:              PopulateDepartmentsDropDownList(); 
 109:              return View(); 
 110:          } 
 111:   
 112:          [HttpPost] 
 113:          public ActionResult Create(Customer customer) 
 114:          { 
 115:              try 
 116:              { 
 117:                  if (ModelState.IsValid) 
 118:                  { 
 119:                      unitOfWork.CustomerRepository.Insert(customer); 
 120:                      unitOfWork.Save(); 
 121:                      return RedirectToAction("Index"); 
 122:                  } 
 123:              } 
 124:              catch (DataException) 
 125:              { 
 126:                  //Log the error (add a variable name after DataException) 
 127:                  ModelState.AddModelError("", "Unable to save changes. Try again, and if the problem persists, see your system administrator."); 
 128:              } 
 129:              PopulateDepartmentsDropDownList(customer.ID); 
 130:              return View(customer); 
 131:          } 
 132:   
 133:          public ActionResult Edit(int id) 
 134:          { 
 135:              Customer customer = unitOfWork.CustomerRepository.GetByID(id); 
 136:              PopulateDepartmentsDropDownList(customer.ID); 
 137:              return View(customer); 
 138:          } 
 139:   
 140:          [HttpPost] 
 141:          public ActionResult Edit(Customer customer) 
 142:          { 
 143:              try 
 144:              { 
 145:                  if (ModelState.IsValid) 
 146:                  { 
 147:                      unitOfWork.CustomerRepository.Update(customer); 
 148:                      unitOfWork.Save(); 
 149:                      return RedirectToAction("Index"); 
 150:                  } 
 151:              } 
 152:              catch (DataException) 
 153:              { 
 154:                  //Log the error (add a variable name after DataException) 
 155:                  ModelState.AddModelError("", "Unable to save changes. Try again, and if the problem persists, see your system administrator."); 
 156:              } 
 157:              
 158:              return View(customer); 
 159:          } 
 160:   
 161:          
 162:   
 163:          // 
 164:          // GET: /Customer/Delete/5 
 165:    
 166:          public ActionResult Delete(int id) 
 167:          { 
 168:              Customer customer = unitOfWork.CustomerRepository.GetByID(id); 
 169:              return View(customer); 
 170:          } 
 171:   
 172:          // 
 173:          // POST: /Customer/Delete/5 
 174:   
 175:          [HttpPost, ActionName("Delete")] 
 176:          public ActionResult DeleteConfirmed(int id) 
 177:          { 
 178:              Customer customer = unitOfWork.CustomerRepository.GetByID(id); 
 179:              unitOfWork.CustomerRepository.Delete(id); 
 180:              unitOfWork.Save(); 
 181:              return RedirectToAction("Index"); 
 182:          } 
 183:   
 184:          protected override void Dispose(bool disposing) 
 185:          { 
 186:              unitOfWork.Dispose(); 
 187:              base.Dispose(disposing); 
 188:          } 
 189:      } 
 190:  }

reference: Tom Dykstra blog
Url:http://www.asp.net/mvc/tutorials/getting-started-with-ef-using-mvc/implementing-the-repository-and-unit-of-work-patterns-in-an-asp-net-mvc-application

Tuesday, June 5, 2012

.NET Web Application with SQL Azure

Windows Azure is a new for me. So why not walkthrough a little bit into it. Before developing a Windows Azure application, let's create a simple MVC web app.

If you do not already have Visual Studio 2010, install windows Azure SDK for .net here

Createing an asp.net MVC3 application

Razor view engine is my favorite.

Run your application locally

Now, you need to prepare your application to run well in a Windows Azure hosted service. The application needs to include a Windows Azure deployment project before it can be deployed to the cloud. The deployment project contains configuration information that is needed to properly run your application in the cloud.

If your application have .net membership provider, use asp.net universal provider. You can download it via Nuget. http://nuget.org/packages/System.Web.Providers

Wednesday, May 30, 2012

Scheduled Tasks in ASP.NET Web Applications using Timers

I'm just found a article that I found on the MSDN blog. And I've just decieded to share on my blog with more explantation.

Before I found this, I honestly had known that the scheduled tasks can be only running on window scheduler tasks.

I had even tried to use Threading with looping to avoid window scheduler tasks on my web application.

Finally, I just found this article .

Scenario: A Web app calls wcf services every one minute. As I'm MVC web developer, my web app is always MVC application. System timer In global.asax, you need to create a Timers method. In below example, I give timer method name to ServiceTimers.

   1:  private void ServiceTimers()
   2:  {
   3:       System.Timers.Timer serivceTimer = new System.Timers.Timer();
   4:       serivceTimer.Enabled = true;
   5:       serivceTimer.Interval = (60000); // one minute
   6:   
   7:       serivceTimer.Elapsed += new
   8:       System.Timers.ElapsedEventHandler(ServiceTimer_Elaspsed);
   9:  }

Within the method, the last line is obviously event handler which call to a event which contains Web service called.

   1:  protected void ServiceTimer_Elaspsed(object sender, System.Timers.ElapsedEventArgs e)
   2:  {
   3:       WorkLoadClient workLoadClient = new WorkLoadClient();
   4:       workLoadClient.DoWork();
   5:  }

All together will be as below in Global.asax

   1:  using System;
   2:  using System.Collections.Generic;
   3:  using System.Linq;
   4:  using System.Web;
   5:  using System.Web.Mvc;
   6:  using System.Web.Routing;
   7:  using NotificationService.Web.ServiceReference2;
   8:   
   9:  namespace NotificationService.Web
  10:  {
  11:      // Note: For instructions on enabling IIS6 or IIS7 classic mode, 
  12:      // visit http://go.microsoft.com/?LinkId=9394801
  13:   
  14:      public class MvcApplication : System.Web.HttpApplication
  15:      {
  16:          public static void RegisterGlobalFilters(GlobalFilterCollection filters)
  17:          {
  18:              filters.Add(new HandleErrorAttribute());
  19:          }
  20:   
  21:          public static void RegisterRoutes(RouteCollection routes)
  22:          {
  23:              routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
  24:   
  25:              routes.MapRoute(
  26:                  "Default", // Route name
  27:                  "{controller}/{action}/{id}", // URL with parameters
  28:                  new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
  29:              );
  30:   
  31:          }
  32:   
  33:          protected void Application_Start()
  34:          {
  35:              AreaRegistration.RegisterAllAreas();
  36:   
  37:              RegisterGlobalFilters(GlobalFilters.Filters);
  38:              RegisterRoutes(RouteTable.Routes);
  39:   
  40:              ServiceTimers();
  41:          }
  42:   
  43:          private void ServiceTimers()
  44:          {
  45:              System.Timers.Timer serivceTimer = new System.Timers.Timer();
  46:              serivceTimer.Enabled = true;
  47:              serivceTimer.Interval = (60000); // one minute
  48:   
  49:              serivceTimer.Elapsed += new
  50:                  System.Timers.ElapsedEventHandler(ServiceTimer_Elaspsed);
  51:          }
  52:   
  53:          protected void ServiceTimer_Elaspsed(object sender, System.Timers.ElapsedEventArgs e)
  54:          {
  55:              WorkLoadClient workLoadClient = new WorkLoadClient();
  56:              workLoadClient.DoWork();
  57:          }
  58:      }
  59:  }

And I have a WCF service project which referenced by Web app.

   1:  using System;
   2:  using System.Collections.Generic;
   3:  using System.Linq;
   4:  using System.Runtime.Serialization;
   5:  using System.ServiceModel;
   6:  using System.Text;
   7:  using System.Threading;
   8:  using System.Net.Mail;
   9:  using System.Net;
  10:   
  11:  namespace NotificationService.Wcf
  12:  {
  13:     
  14:      public class WorkLoad : IWorkLoad
  15:      {       
  16:          public void DoWork()
  17:          {            
  18:              var client = new SmtpClient("smtp.gmail.com", 587)
  19:              {
  20:                  Credentials = new NetworkCredential("xxxx@gmail.com", "xxxxxx"),
  21:                  EnableSsl = true
  22:              };
  23:   
  24:              client.Send("xxx@gmail.com", "xxxx@email.com", "test", "testbody");
  25:            
  26:          }
  27:          
  28:      }
  29:  }
reference:http://weblogs.asp.net/samirgeorge/archive/2009/05/09/scheduled-task-in-asp-net-web-application-using-timers.aspx

Tuesday, May 29, 2012

C#Asp.net MVC Export CSV ActionResult

Exporting Csv format at MVC is extremely easy. In fact, with clean codes. My scenario: Lead data stores in a database. From the one click event which named download will pop out csv file to download.

The following code I found on develoq.net blog which is very useful. Literally, just drop that in and call it in actionresult from controller page.

   1:   public sealed class CsvActionResult : FileResult
   2:      {
   3:          private readonly DataTable dataTable;
   4:          public CsvActionResult(DataTable dataTable)
   5:              : base("text/csv")
   6:          {
   7:              this.dataTable = dataTable;
   8:          }
   9:   
  10:          protected override void WriteFile(HttpResponseBase response)
  11:          {
  12:              var outputStream = response.OutputStream;
  13:              using (var memoryStream = new MemoryStream())
  14:              {
  15:                  WriteDataTable(memoryStream);
  16:                  outputStream.Write(memoryStream.GetBuffer(), 0, (int)memoryStream.Length);
  17:              }
  18:          }
  19:   
  20:          private void WriteDataTable(Stream stream)
  21:          {
  22:              var streamWriter = new StreamWriter(stream, Encoding.Default);
  23:   
  24:              WriteHeaderLine(streamWriter);
  25:              streamWriter.WriteLine();
  26:              WriteDataLines(streamWriter);
  27:   
  28:              streamWriter.Flush();
  29:          }
  30:          
  31:          private void WriteHeaderLine(StreamWriter streamWriter)
  32:          {
  33:              foreach (DataColumn dataColumn in dataTable.Columns)
  34:              {
  35:                  WriteValue(streamWriter, dataColumn.ColumnName);
  36:              }
  37:          }
  38:   
  39:          private void WriteDataLines(StreamWriter streamWriter)
  40:          {
  41:              foreach (DataRow dataRow in dataTable.Rows)
  42:              {
  43:                  foreach (DataColumn dataColumn in dataTable.Columns)
  44:                  {
  45:                      WriteValue(streamWriter, dataRow[dataColumn.ColumnName].ToString());
  46:                  }
  47:                  streamWriter.WriteLine();
  48:              }
  49:          }
  50:   
  51:          private static void WriteValue(StreamWriter writer, String value)
  52:          {
  53:              writer.Write("\"");
  54:              writer.Write(value.Replace("\"", "\"\""));
  55:              writer.Write("\",");
  56:          }
  57:   
  58:      }

Using by Datatable to manipulate data to display in Excel sheet. The following actionresult to fire when the download button clicked. And you can see how to read the model to datatable dynamically.

You can see the first loop is for table column name to display. And I use another loop to populate the data to right column.

   1:   [HttpPost]
   2:          public ActionResult Report(int formId)
   3:          {
   4:              DataTable table = new DataTable();
   5:              var formFieldList = formFieldRepo.Where(m => m.FormId == formId);
   6:              var formEntries = formEntryRepo.Where(m => m.FormId == formId);
   7:   
   8:              foreach (var item in formFieldList)
   9:              {
  10:                  table.Columns.Add(item.Title, typeof(string));
  11:                  //string[] rows = item.valu
  12:              }
  13:   
  14:              foreach (var item in formEntries)
  15:              {
  16:                  string[] rows = item.Value.Split(',');
  17:   
  18:                  DataRow dataRow = table.NewRow();
  19:                  foreach (var rowItem in rows)
  20:                  {
  21:                      if (!string.IsNullOrEmpty(rowItem))
  22:                      {
  23:                          dataRow[rowItem.Split('/').First().ToString()] = rowItem.Split('/').Last().ToString();
  24:                      }
  25:                  }
  26:                  table.Rows.Add(dataRow);
  27:              }
  28:   
  29:              return new CsvActionResult(table) { FileDownloadName = "ExportedFile.csv" };
  30:          }

Any questions and different opnions are warmly welcomed.

Sunday, May 27, 2012

MVC Webapi


Today, I'm posting about WebApi. Recently, I've looked some example of Webapi on other blogs. Recently, found some of other people's conversation from other sites.

1.Introduction to HttpClient HttpClient provides a flexible and extensible API for accessing all things exposed through HTTP. We used to use it for a while as part of WCF Web API. It is now part of ASP.NET Web API and in .NET 4.5 which is make developer to easier to develop.
System.Net.Http: it provides the basic HttpClient and related classes System.Net.Http.Formatting: Adds support for serialization, deserialization as well as for many additional features building on top of System.Net.Http System.Json: it is for JsonVaue which is a mechanism for reading and manipulating JSON documents
Please see below the sample code which I found it on msdn blog (http://code.msdn.microsoft.com/Introduction-to-HttpClient-4a2d9cee)

   1:  static void Main(string[] args) 
   2:          { 
   3:              // Create an HttpClient instance 
   4:              HttpClient client = new HttpClient(); 
   5:   
   6:              // Send a request asynchronously continue when complete 
   7:              client.GetAsync(_address).ContinueWith( 
   8:                  (requestTask) => 
   9:                  { 
  10:                      // Get HTTP response from completed task. 
  11:                      HttpResponseMessage response = requestTask.Result; 
  12:   
  13:                      // Check that response was successful or throw exception 
  14:                      response.EnsureSuccessStatusCode(); 
  15:   
  16:                      // Read response asynchronously as JsonValue and write out top facts for each country 
  17:                      response.Content.ReadAsAsync<JsonArray>().ContinueWith( 
  18:                          (readTask) => 
  19:                          { 
  20:                              Console.WriteLine("First 50 countries listed by The World Bank..."); 
  21:                              foreach (var country in readTask.Result[1]) 
  22:                              { 
  23:                                  Console.WriteLine("   {0}, Country Code: {1}, Capital: {2}, Latitude: {3}, Longitude: {4}", 
  24:                                      country.Value["name"], 
  25:                                      country.Value["iso2Code"], 
  26:                                      country.Value["capitalCity"], 
  27:                                      country.Value["latitude"], 
  28:                                      country.Value["longitude"]); 
  29:                              } 
  30:                          }); 
  31:                  }); 
  32:   
  33:              Console.WriteLine("Hit ENTER to exit..."); 
  34:              Console.ReadLine(); 
  35:          }

Just a little defination for HttpClient: Itis the main class for sending and receiving HttpRequestMessages and HttpResponseMessages. If you are used to using WebClient or HttpWebRequest.

An HttpClient instance is the place to configure extensions, set default headers, cancel outstanding requests and more.

  1. You can issue as many requests as you like through a single HttpClient instance.
  2. HttpClients are not tied to particular HTTP server or host; you can submit any HTTP request using the same HttpClient instance.
  3. You can derive from HttpClient to create specialized clients for particular sites or patterns
  4. HttpClient uses the new Task-oriented pattern for handling asynchronous requests making it dramatically easier to manage and coordinate multiple outstanding requests.

As you know HttpResponseMessage contains information about the response including the status code, headers, and any content body.

The content body is encapsulated in HttpContent which captures content headers such as Content-Type, Content-Encoding. we can read the content as JsonArray as well as any number of ReadAs* methods.

please see the more deail here http://blogs.msdn.com/b/henrikn/archive/2012/02/11/httpclient-is-here.aspx
public class Contact
{
    public int Id { get; set; }
    public string Name { get; set; }
}
   1:  var url = "http://localhost:9000/api/contacts";
   2:  using (var client = new WebClient())
   3:  using (var reader = XmlReader.Create(client.OpenRead(url)))
   4:  {
   5:      var serializer = new XmlSerializer(typeof(Contact[]));
   6:      var contacts = (Contact[])serializer.Deserialize(reader);
   7:      // TODO: Do something with the contacts
   8:  }

Monday, March 19, 2012

Multiple file upload with MVC 3

   1: public ActionResult Upload()
2: {
3: return View();
4: }
5:
6: [HttpPost]
7: public ActionResult Upload(IEnumerable<HttpPostedFileBase> fileUpload)
8: {
9: foreach (var file in fileUpload)
10: {
11: if (file.ContentLength > 0)
12: {
13: var fileName = Path.GetFileName(file.FileName);
14: var path = Path.Combine(Server.MapPath("~/App_Data/uploads"), fileName);
15: file.SaveAs(path);
16: }
17: }
18: return RedirectToAction("Index");
19: }
Microsoft Web Helper is very handy to use. Above example is shown how to use MS Web helper's Multiple file upload.

See below how the ui should be implement for Muliple file upload.



 <h2>Upload</h2>       
@FileUpload.GetHtml(5, uploadText: "Upload files")

Tuesday, February 7, 2012

Interview questions ASP.Net 4.0

Today, I'm posting some question for Asp.net Framework 4.

Q. What is new with ASP.Net 4 WebForms ?

Ans. Some of the Features are:

. Ability to Set Metatags.
. More control over view state.
. Added and Updated browser definition files.
. ASP.Net Routing.
. The ability to Persist Selected rows in data Control.
. More control over rendered HTML in FormView and ListView Controls.
. Filtering Support for datasource Controls.


Q. What is machine.config file and how do you use it in ASP.Net 4.0?

Ans. Machine.Config file is found in the "CONFIG" subfolder of your .NET Framework install directory (c:\WINNT\Microsoft.NET\Framework\{Version Number}\CONFIG on Windows 2000 installations). It contains configuration settings for machine-wide assembly binding, built-in remoting channels, and ASP.NET.

In .the NET Framework 4.0, the major configuration elements(that use to be in web.config) have been moved to the machine.config file, and the applications now inherit these settings. This allows the Web.config file in ASP.NET 4 applications either to be empty or to contain just the following lines.


Q. What is RedirectPermanent in ASP.Net 4.0?

Ans. In earlier Versions of .Net, Response.Redirect was used, which issues an HTTP 302 Found or temporary redirect response to the browser (meaning that asked resource is temporarily moved to other location) which inturn results in an extra HTTP round trip. ASP.NET 4.0 however, adds a new RedirectPermanent that Performs a permanent redirection from the requested URL to the specified URL. and returns 301 Moved Permanently responses.
e.g. RedirectPermanent("/newpath/foroldcontent.aspx");


Q. How will you specify what version of the framework your application is targeting?

Ans. In Asp.Net 4 a new element "targetFramework" of compilation tag (in Web.config file) lets you specify the framework version in the webconfig file

It only lets you target the .NET Framework 4.0 and later verisons.


Q. What is the use of MetaKeywords and MetaDescription properties.

Ans. MetaKeywords and MetaDescription are the new properties added to the Page class of ASP.NET 4.0 Web Forms. The two properties are used to set the keywords and description meta tags in your page.
For e.g.



You can set these properties at run time, which lets you get the content from a database or other source, and which lets you set the tags dynamically to describe what a particular page is for.

You can also set the Keywords and Description properties in the @ Page directive at the top of the Web Forms page markup like,
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" Keywords="ASP,4.0,are keywords" Description="blah blah" %>


Q. What is Microsoft Ajax Library.

Ans. Microsoft Ajax Library is a client-only JavaScript library that is compatible with all modern browsers, including Internet Explorer, Google Chrome, Apple Safari, and Mozilla Firefox.Because the Microsoft Ajax Library is a client-only JavaScript library, you can use the library with both ASP.NET Web Forms and ASP.NET MVC applications. You can also create Ajax pages that consist only of HTML.


Q. What are the Changes in CheckBoxList and RadioButtonList Control ?

Ans. In ASP.NET 4, the CheckBoxList and RadioButtonList controls support two new values for the RepeatLayout property, OrderedList(The content is rendered as li elements within an ol element) and UnorderedList(The content is rendered as li elements within a ul element.)
For more info see : Specify Layout in CheckBoxList and RadioButtonList Control - ASP.Net 4


Q. Whats Application Warm-Up Module?

Ans. We can set-up a Warm-Up module for warming up your applications before they serve their first request.Instead of writing custom code, you specify the URLs of resources to execute before the Web application accepts requests from the network. This warm-up occurs during startup of the IIS service (if you configured the IIS application pool as AlwaysRunning) and when an IIS worker process recycles. During recycle, the old IIS worker process continues to execute requests until the newly spawned worker process is fully warmed up, so that applications experience no interruptions or other issues due to unprimed caches.

Monday, February 6, 2012

Html Raw of Asp.net MVC 3 with Razor view engine

Today, I'm posting about HTML Raw of MVC3 Razor View engine.

HtmlString IHtmlString and HttpUtlity.HtmlEncode in ASP.NET 4 are fantastic features.

Saving Content in Database, retrieve it dynamically on Front end page that is absolutely nice.

HtmlHelper.Raw Method wraps HTML markup using the IHtmlString class, which renders unencoded HTML.


   1:  public IHtmlString Raw(
2: string value 3: )



   1:  @{ var para = "<p>I am a parargraph</p>";}
   2:  @Html.Raw(para)

Sunday, February 5, 2012

LinkedList(Of T) Class C#

Today, I'm posting to about LinkedList class. LinkedList is one of System.Collections.Generic collection classes.

What LinkedList class can do:
You can remove nodes and reinsert them, either in the same list or in another list, which results in no additional object allocated on the heap. LinkedList accepts null value.

Please note: LinkedList class doesn't support chaining, splitting, cycles or other features that can leave the list in inconsistent state. The list remains consistent on a signle thread. The Linkedlist supports multithread read.

Please see the following examples:



   1:  using System;

   2:  using System.Text;

   3:  using System.Collections.Generic;

   4:   

   5:  public class Example

   6:  {

   7:      public static void Main()

   8:      {

   9:          // Create the link list.

  10:          string[] words =

  11:              { "the", "fox", "jumped", "over", "the", "dog" };

  12:          LinkedList<string> sentence = new LinkedList<string>(words);

  13:          Display(sentence, "The linked list values:");

  14:          Console.WriteLine("sentence.Contains(\"jumped\") = {0}",

  15:              sentence.Contains("jumped"));

  16:   

  17:          // Add the word 'today' to the beginning of the linked list.

  18:          sentence.AddFirst("today");

  19:          Display(sentence, "Test 1: Add 'today' to beginning of the list:");

  20:   

  21:          // Move the first node to be the last node.

  22:          LinkedListNode<string> mark1 = sentence.First;

  23:          sentence.RemoveFirst();

  24:          sentence.AddLast(mark1);

  25:          Display(sentence, "Test 2: Move first node to be last node:");

  26:   

  27:          // Change the last node be 'yesterday'.

  28:          sentence.RemoveLast();

  29:          sentence.AddLast("yesterday");

  30:          Display(sentence, "Test 3: Change the last node to 'yesterday':");

  31:   

  32:          // Move the last node to be the first node.

  33:          mark1 = sentence.Last;

  34:          sentence.RemoveLast();

  35:          sentence.AddFirst(mark1);

  36:          Display(sentence, "Test 4: Move last node to be first node:");

  37:   

  38:   

  39:          // Indicate, by using parentheisis, the last occurence of 'the'.

  40:          sentence.RemoveFirst();

  41:          LinkedListNode<string> current = sentence.FindLast("the");

  42:          IndicateNode(current, "Test 5: Indicate last occurence of 'the':");

  43:   

  44:          // Add 'lazy' and 'old' after 'the' (the LinkedListNode named current).

  45:          sentence.AddAfter(current, "old");

  46:          sentence.AddAfter(current, "lazy");

  47:          IndicateNode(current, "Test 6: Add 'lazy' and 'old' after 'the':");

  48:   

  49:          // Indicate 'fox' node.

  50:          current = sentence.Find("fox");

  51:          IndicateNode(current, "Test 7: Indicate the 'fox' node:");

  52:   

  53:          // Add 'quick' and 'brown' before 'fox':

  54:          sentence.AddBefore(current, "quick");

  55:          sentence.AddBefore(current, "brown");

  56:          IndicateNode(current, "Test 8: Add 'quick' and 'brown' before 'fox':");

  57:   

  58:          // Keep a reference to the current node, 'fox',

  59:          // and to the previous node in the list. Indicate the 'dog' node.

  60:          mark1 = current;

  61:          LinkedListNode<string> mark2 = current.Previous;

  62:          current = sentence.Find("dog");

  63:          IndicateNode(current, "Test 9: Indicate the 'dog' node:");

  64:   

  65:          // The AddBefore method throws an InvalidOperationException

  66:          // if you try to add a node that already belongs to a list.

  67:          Console.WriteLine("Test 10: Throw exception by adding node (fox) already in the list:");

  68:          try

  69:          {

  70:              sentence.AddBefore(current, mark1);

  71:          }

  72:          catch (InvalidOperationException ex)

  73:          {

  74:              Console.WriteLine("Exception message: {0}", ex.Message);

  75:          }

  76:          Console.WriteLine();

  77:   

  78:          // Remove the node referred to by mark1, and then add it

  79:          // before the node referred to by current.

  80:          // Indicate the node referred to by current.

  81:          sentence.Remove(mark1);

  82:          sentence.AddBefore(current, mark1);

  83:          IndicateNode(current, "Test 11: Move a referenced node (fox) before the current node (dog):");

  84:   

  85:          // Remove the node referred to by current.

  86:          sentence.Remove(current);

  87:          IndicateNode(current, "Test 12: Remove current node (dog) and attempt to indicate it:");

  88:   

  89:          // Add the node after the node referred to by mark2.

  90:          sentence.AddAfter(mark2, current);

  91:          IndicateNode(current, "Test 13: Add node removed in test 11 after a referenced node (brown):");

  92:   

  93:          // The Remove method finds and removes the

  94:          // first node that that has the specified value.

  95:          sentence.Remove("old");

  96:          Display(sentence, "Test 14: Remove node that has the value 'old':");

  97:   

  98:          // When the linked list is cast to ICollection(Of String),

  99:          // the Add method adds a node to the end of the list.

 100:          sentence.RemoveLast();

 101:          ICollection<string> icoll = sentence;

 102:          icoll.Add("rhinoceros");

 103:          Display(sentence, "Test 15: Remove last node, cast to ICollection, and add 'rhinoceros':");

 104:   

 105:          Console.WriteLine("Test 16: Copy the list to an array:");

 106:          // Create an array with the same number of

 107:          // elements as the inked list.

 108:          string[] sArray = new string[sentence.Count];

 109:          sentence.CopyTo(sArray, 0);

 110:   

 111:          foreach (string s in sArray)

 112:          {

 113:              Console.WriteLine(s);

 114:          }

 115:   

 116:          // Release all the nodes.

 117:          sentence.Clear();

 118:   

 119:          Console.WriteLine();

 120:          Console.WriteLine("Test 17: Clear linked list. Contains 'jumped' = {0}",

 121:              sentence.Contains("jumped"));

 122:   

 123:          Console.ReadLine();

 124:      }

 125:   

 126:      private static void Display(LinkedList<string> words, string test)

 127:      {

 128:          Console.WriteLine(test);

 129:          foreach (string word in words)

 130:          {

 131:              Console.Write(word + " ");

 132:          }

 133:          Console.WriteLine();

 134:          Console.WriteLine();

 135:      }

 136:   

 137:      private static void IndicateNode(LinkedListNode<string> node, string test)

 138:      {

 139:          Console.WriteLine(test);

 140:          if (node.List == null)

 141:          {

 142:              Console.WriteLine("Node '{0}' is not in the list.\n",

 143:                  node.Value);

 144:              return;

 145:          }

 146:   

 147:          StringBuilder result = new StringBuilder("(" + node.Value + ")");

 148:          LinkedListNode<string> nodeP = node.Previous;

 149:   

 150:          while (nodeP != null)

 151:          {

 152:              result.Insert(0, nodeP.Value + " ");

 153:              nodeP = nodeP.Previous;

 154:          }

 155:   

 156:          node = node.Next;

 157:          while (node != null)

 158:          {

 159:              result.Append(" " + node.Value);

 160:              node = node.Next;

 161:          }

 162:   

 163:          Console.WriteLine(result);

 164:          Console.WriteLine();

 165:      }

 166:  }

 167:   

 168:  //This code example produces the following output:

 169:  //

 170:  //The linked list values:

 171:  //the fox jumped over the dog

 172:   

 173:  //Test 1: Add 'today' to beginning of the list:

 174:  //today the fox jumped over the dog

 175:   

 176:  //Test 2: Move first node to be last node:

 177:  //the fox jumped over the dog today

 178:   

 179:  //Test 3: Change the last node to 'yesterday':

 180:  //the fox jumped over the dog yesterday

 181:   

 182:  //Test 4: Move last node to be first node:

 183:  //yesterday the fox jumped over the dog

 184:   

 185:  //Test 5: Indicate last occurence of 'the':

 186:  //the fox jumped over (the) dog

 187:   

 188:  //Test 6: Add 'lazy' and 'old' after 'the':

 189:  //the fox jumped over (the) lazy old dog

 190:   

 191:  //Test 7: Indicate the 'fox' node:

 192:  //the (fox) jumped over the lazy old dog

 193:   

 194:  //Test 8: Add 'quick' and 'brown' before 'fox':

 195:  //the quick brown (fox) jumped over the lazy old dog

 196:   

 197:  //Test 9: Indicate the 'dog' node:

 198:  //the quick brown fox jumped over the lazy old (dog)

 199:   

 200:  //Test 10: Throw exception by adding node (fox) already in the list:

 201:  //Exception message: The LinkedList node belongs a LinkedList.

 202:   

 203:  //Test 11: Move a referenced node (fox) before the current node (dog):

 204:  //the quick brown jumped over the lazy old fox (dog)

 205:   

 206:  //Test 12: Remove current node (dog) and attempt to indicate it:

 207:  //Node 'dog' is not in the list.

 208:   

 209:  //Test 13: Add node removed in test 11 after a referenced node (brown):

 210:  //the quick brown (dog) jumped over the lazy old fox

 211:   

 212:  //Test 14: Remove node that has the value 'old':

 213:  //the quick brown dog jumped over the lazy fox

 214:   

 215:  //Test 15: Remove last node, cast to ICollection, and add 'rhinoceros':

 216:  //the quick brown dog jumped over the lazy rhinoceros

 217:   

 218:  //Test 16: Copy the list to an array:

 219:  //the

 220:  //quick

 221:  //brown

 222:  //dog

 223:  //jumped

 224:  //over

 225:  //the

 226:  //lazy

 227:  //rhinoceros

 228:   

 229:  //Test 17: Clear linked list. Contains 'jumped' = False

 230:  //



  


// ( reference to MSDN: msdn.microsoft.com/en-us/library/he2s3bh7.aspx)