Comments on: Bulletproof Ajax with ASP.NET MVC http://gaskell.org/bulletproof-ajax-with-aspnet-mvc/ picking up where teh rest leave off Tue, 27 Mar 2012 02:02:23 +0000 hourly 1 http://wordpress.org/?v=3.3.2 By: Dan http://gaskell.org/bulletproof-ajax-with-aspnet-mvc/comment-page-1/#comment-14025 Dan Tue, 05 Aug 2008 17:00:50 +0000 http://gaskell.org/?p=59#comment-14025 @Andy, Thanks for the post. I just bought this book but haven't read it yet. I've been playing around with ASP.NET MVC too so this exact topic has been on my mind. @Matthew, it seems by your comments that you are not aware of the "Bulletproof Ajax" book. I don't think Andy is trying to propose the right way to do Ajax in ASP.NET MVC. Instead I think he is trying to show how the lessons learned in Bulletproof Ajax might fit into ASP.NET MVC. With respect to the Model I disagree with Matthew... the model should not have any knowledge of HttpSession (or anything else in System.Web*). Decoupling domain objects from the persistence store is a good thing (tm) - I'm not arguing that. But there is a difference between Session State Patterns and Data Source Patterns. HttpSession falls into the former category and is a concern of the Controller. To prove the point... ShoppingCart is an entity in your example. Whether that entity is transient and dies when the session dies or persistent is a feature of the application. In the first case the controller would need a Session State pattern (Server Session State) but in the second case would need a Data Access pattern (Table Data Gateway, Row Data Gateway, Active Record, Data Mapper). Cheers, Dan ref: http://martinfowler.com/eaaCatalog/ @Andy,

Thanks for the post. I just bought this book but haven’t read it yet. I’ve been playing around with ASP.NET MVC too so this exact topic has been on my mind.

@Matthew, it seems by your comments that you are not aware of the “Bulletproof Ajax” book. I don’t think Andy is trying to propose the right way to do Ajax in ASP.NET MVC. Instead I think he is trying to show how the lessons learned in Bulletproof Ajax might fit into ASP.NET MVC.

With respect to the Model I disagree with Matthew… the model should not have any knowledge of HttpSession (or anything else in System.Web*). Decoupling domain objects from the persistence store is a good thing ™ – I’m not arguing that. But there is a difference between Session State Patterns and Data Source Patterns. HttpSession falls into the former category and is a concern of the Controller.

To prove the point… ShoppingCart is an entity in your example. Whether that entity is transient and dies when the session dies or persistent is a feature of the application. In the first case the controller would need a Session State pattern (Server Session State) but in the second case would need a Data Access pattern (Table Data Gateway, Row Data Gateway, Active Record, Data Mapper).

Cheers,
Dan

ref: http://martinfowler.com/eaaCatalog/

]]>
By: Matthew http://gaskell.org/bulletproof-ajax-with-aspnet-mvc/comment-page-1/#comment-13990 Matthew Mon, 04 Aug 2008 13:59:33 +0000 http://gaskell.org/?p=59#comment-13990 The Model is resposible for the management of data or state. The means of storage, session, xml, sql, etc., should be transparent to the user. If you program to an Interface, then you can substitute alternate implementations as required. There is good support in APS.NET MVC, and several blog articles, on how to implement AJAX patterns in your MVC code. try http://www.hanselman.com/blog/ASPNETMVCPreview4UsingAjaxAndAjaxForm.aspx The Model is resposible for the management of data or state. The means of storage, session, xml, sql, etc., should be transparent to the user. If you program to an Interface, then you can substitute alternate implementations as required.

There is good support in APS.NET MVC, and several blog articles, on how to implement AJAX patterns in your MVC code.
try http://www.hanselman.com/blog/ASPNETMVCPreview4UsingAjaxAndAjaxForm.aspx

]]>
By: andy gaskell http://gaskell.org/bulletproof-ajax-with-aspnet-mvc/comment-page-1/#comment-13961 andy gaskell Mon, 04 Aug 2008 01:50:12 +0000 http://gaskell.org/?p=59#comment-13961 Thanks for the feedback Matthew. Most of the articles and examples I've seen so far use TempData (sort of a toned down Session object) in the Controllers and sometimes views. I'm not really sure if the Model should be responsible for state management - It would be nice to reuse the Model in non-web applications if need be. Regarding routes - I don't know a whole lot about routes. I'll do more reading up on them. However Hijax is supposed to be making the request to a different url. This allows us to return html fragments if the client is ajax enabled. Try turning off javascript (or removing Hijax) - the request will be handled by the Home controller. What made sense to me was that the Home controller would be responsible for full page requests and the Ratings/Cart controllers would be responsible for their fragments of html. Thanks for the feedback Matthew. Most of the articles and examples I’ve seen so far use TempData (sort of a toned down Session object) in the Controllers and sometimes views. I’m not really sure if the Model should be responsible for state management – It would be nice to reuse the Model in non-web applications if need be.

Regarding routes – I don’t know a whole lot about routes. I’ll do more reading up on them. However Hijax is supposed to be making the request to a different url. This allows us to return html fragments if the client is ajax enabled. Try turning off javascript (or removing Hijax) – the request will be handled by the Home controller. What made sense to me was that the Home controller would be responsible for full page requests and the Ratings/Cart controllers would be responsible for their fragments of html.

]]>
By: Matthew http://gaskell.org/bulletproof-ajax-with-aspnet-mvc/comment-page-1/#comment-13960 Matthew Mon, 04 Aug 2008 01:11:59 +0000 http://gaskell.org/?p=59#comment-13960 The post stripped the <Product, string> from the Dictionary in Cart.cs and Rating.cs The post stripped the <Product, string> from the Dictionary in Cart.cs and Rating.cs

]]>
By: Matthew http://gaskell.org/bulletproof-ajax-with-aspnet-mvc/comment-page-1/#comment-13959 Matthew Mon, 04 Aug 2008 01:07:18 +0000 http://gaskell.org/?p=59#comment-13959 A couple of issues with what you have so far: 1. you have the controllers implementing model functionality. 2. your Hijax.js code is modifying the URL which messes thinks up if you change the routes, particularly to pass parameter like routes.MapRoute( "RateProduct", // Route name "Rating/{action}/{productid}/{ratingVal}", // URL with parameters new { controller = "Rating", action = "RateProduct", productid = "", ratingVal = "" } // Parameter defaults ); I've modified the code for the controllers to using System.Web; using System.Web.Mvc; using BulletproofShop.Models; namespace BulletproofShop.Controllers { public class RatingController : Controller { private const string YOUR_RATING = "Your rating:"; private const string RATE_THIS_BOOK = "Rate this book:"; public class ProductRatingViewData { public string Rating { get; set; } public string RatingMessage { get; set; } public Product Product { get; set; } } public ActionResult DisplayRating(Product product) { Rating ratings = new Rating(); string rating = null; string ratingMessage = RATE_THIS_BOOK; if (ratings.Ratings.ContainsKey(product)) { rating = ratings.Ratings[product]; ratingMessage = YOUR_RATING; } return View("Rating", new ProductRatingViewData { Product = product, Rating = rating, RatingMessage = ratingMessage }); } public ActionResult RateProduct(string productid, string ratingVal) { //RatingController ratingController = new RatingController(); //ratingController.RateProduct(productID, rating); Rating ratings = new Rating(); ratings.SetRating(productid, ratingVal); return RedirectToAction("Index", "Home"); } } } -------------------------------- using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; using BulletproofShop.Models; namespace BulletproofShop.Controllers { [HandleError] public class HomeController : Controller { public ActionResult Index() { ViewData.Model = Product.Products; return View("Index"); } public ActionResult AddProductToCart(string productid, int quantity) { Cart cart = new Cart(); cart.AddProduct(productid, quantity); return Index(); } } } ----------------------------- using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; using BulletproofShop.Models; namespace BulletproofShop.Controllers { public class CartController : Controller { // I'm sure there's a better way to handle state management. I just don't know what it is. public ActionResult DisplayCart() { Cart cart = new Cart(); return View("Cart", cart); } } } ---------------------------- and the models to namespace BulletproofShop.Models { public class Cart { Dictionary contents ; public Cart() { contents = Contents; } public Dictionary Contents { get { contents = System.Web.HttpContext.Current.Session["Cart"] as Dictionary; if (contents == null) { contents = new Dictionary(); } return contents; } } public void AddProduct(Product product, int quantity) { if(Contents.ContainsKey(product)) { contents[product] += quantity; } else { contents.Add(product, quantity); } System.Web.HttpContext.Current.Session["Cart"] = contents; } public void AddProduct(string productID, int quantity) { Product product = Product.Products.Find(s => s.ID == productID); AddProduct(product, quantity); } } } -------------------------- using System; using System.Data; using System.Collections.Generic; using System.Configuration; using System.Linq; using System.Web; using System.Web.Security; using System.Web.UI; using System.Web.UI.HtmlControls; using System.Web.UI.WebControls; using System.Web.UI.WebControls.WebParts; using System.Xml.Linq; namespace BulletproofShop.Models { public class Rating { Dictionary ratings ; public Rating() { ratings = Ratings; } public Dictionary Ratings { get { if (ratings == null) { ratings = System.Web.HttpContext.Current.Session["Rating"] as Dictionary; { if (ratings == null) ratings = new Dictionary(); } } return ratings; } } public void SetRating(Product product, string rating) { if (Ratings.ContainsKey(product)) { ratings[product] = rating; } else { ratings.Add(product, rating); } System.Web.HttpContext.Current.Session["Rating"] = ratings; } public void SetRating(string productID, string rating) { Product product = Product.Products.Find(s => s.ID == productID); SetRating(product, rating); } } } --------------------------- with Product unchanged. I made some hacks to Hijax.js to stop it changing the URL but need to look at it more to understand if this file is needed at all. A couple of issues with what you have so far:
1. you have the controllers implementing model functionality.

2. your Hijax.js code is modifying the URL which messes thinks up if you change the routes, particularly to pass parameter like
routes.MapRoute(
“RateProduct”, // Route name
“Rating/{action}/{productid}/{ratingVal}”, // URL with parameters
new { controller = “Rating”, action = “RateProduct”, productid = “”, ratingVal = “” } // Parameter defaults
);
I’ve modified the code for the controllers to
using System.Web;
using System.Web.Mvc;
using BulletproofShop.Models;

namespace BulletproofShop.Controllers
{
public class RatingController : Controller
{
private const string YOUR_RATING = “Your rating:”;
private const string RATE_THIS_BOOK = “Rate this book:”;

public class ProductRatingViewData
{
public string Rating { get; set; }
public string RatingMessage { get; set; }
public Product Product { get; set; }
}

public ActionResult DisplayRating(Product product)
{
Rating ratings = new Rating();
string rating = null;
string ratingMessage = RATE_THIS_BOOK;
if (ratings.Ratings.ContainsKey(product))
{
rating = ratings.Ratings[product];
ratingMessage = YOUR_RATING;
}
return View(“Rating”, new ProductRatingViewData { Product = product, Rating = rating, RatingMessage = ratingMessage });
}

public ActionResult RateProduct(string productid, string ratingVal)
{
//RatingController ratingController = new RatingController();
//ratingController.RateProduct(productID, rating);
Rating ratings = new Rating();
ratings.SetRating(productid, ratingVal);
return RedirectToAction(“Index”, “Home”);
}

}
}

——————————–

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using BulletproofShop.Models;

namespace BulletproofShop.Controllers
{
[HandleError]
public class HomeController : Controller
{
public ActionResult Index()
{
ViewData.Model = Product.Products;
return View(“Index”);
}

public ActionResult AddProductToCart(string productid, int quantity)
{
Cart cart = new Cart();
cart.AddProduct(productid, quantity);
return Index();
}
}
}
—————————–
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using BulletproofShop.Models;

namespace BulletproofShop.Controllers
{
public class CartController : Controller
{
// I’m sure there’s a better way to handle state management. I just don’t know what it is.

public ActionResult DisplayCart()
{
Cart cart = new Cart();
return View(“Cart”, cart);
}
}
}
—————————-
and the models to
namespace BulletproofShop.Models
{
public class Cart
{
Dictionary contents ;

public Cart()
{
contents = Contents;
}

public Dictionary Contents
{
get
{
contents = System.Web.HttpContext.Current.Session["Cart"] as Dictionary;
if (contents == null)
{
contents = new Dictionary();
}
return contents;
}
}

public void AddProduct(Product product, int quantity)
{
if(Contents.ContainsKey(product))
{
contents[product] += quantity;
}
else
{
contents.Add(product, quantity);
}
System.Web.HttpContext.Current.Session["Cart"] = contents;
}

public void AddProduct(string productID, int quantity)
{
Product product = Product.Products.Find(s => s.ID == productID);
AddProduct(product, quantity);
}

}
}
————————–
using System;
using System.Data;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;

namespace BulletproofShop.Models
{
public class Rating
{
Dictionary ratings ;

public Rating()
{
ratings = Ratings;
}

public Dictionary Ratings
{
get
{
if (ratings == null)
{
ratings = System.Web.HttpContext.Current.Session["Rating"] as Dictionary;
{
if (ratings == null)
ratings = new Dictionary();
}
}
return ratings;
}
}

public void SetRating(Product product, string rating)
{
if (Ratings.ContainsKey(product))
{
ratings[product] = rating;
}
else
{
ratings.Add(product, rating);
}
System.Web.HttpContext.Current.Session["Rating"] = ratings;
}

public void SetRating(string productID, string rating)
{
Product product = Product.Products.Find(s => s.ID == productID);
SetRating(product, rating);
}
}
}
—————————
with Product unchanged.

I made some hacks to Hijax.js to stop it changing the URL but need to look at it more to understand if this file is needed at all.

]]>
By: ASP.NET MVC Archived Blog Posts, Page 1 http://gaskell.org/bulletproof-ajax-with-aspnet-mvc/comment-page-1/#comment-13946 ASP.NET MVC Archived Blog Posts, Page 1 Sun, 03 Aug 2008 17:34:43 +0000 http://gaskell.org/?p=59#comment-13946 [...] to VoteBulletproof Ajax with ASP.NET MVC (8/2/2008)Saturday, August 02, 2008 from andy gaskellNET MVC would be a great first attempt at building an [...] [...] to VoteBulletproof Ajax with ASP.NET MVC (8/2/2008)Saturday, August 02, 2008 from andy gaskellNET MVC would be a great first attempt at building an [...]

]]>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 Buy Generic Methotrexate No Prescription Viagra Walmart Best Online Pharmacy For Cialis Generic Buying Femara Canadian Pharmacy No Prescription Needed Alesse Purchase No Prescription Mircette Cheapest Levitra From India Buy Tablets Actonel Online No Prescription Antibiotics Online Ordina Viagra Tricor No Prescription Acheter Diabecon Viagra Ou Equivalentes Amoxil Buy Online Cheap Cafergot Order Buy Best Generic Baclofen Tablets Without a Prescription Seroquel Order Online No Perscription Purchase Lexapro Online Without Prescription Buy Viagra Online Tabs Cheap Generic Substitute Viagra Purchase Lexapro Purchase Viagra In Australia Buy Viagra In Canada Fast Canadian Pharmacy Toronto Zithromax Order Bupropion Next Day Delivery Canadianlab Viagra Tablets Buy VentolinZovirax And Cost Levitra 20mg Tablets Generic Viagra Free Pills Viagra Professional Buy