Wednesday, November 10, 2010

ASP.NET MVC ajax request image caching.

I've meet a problem in ASP.NET ajax request. Here's the scenario.

  • I upload a file using ajax (image to be exact).
  • Saved the file in a certain location.
  • I need the file name to be the saved as the single file name for each user, for example user1 should have an image of user1_pic.jpg.
  • If I upload another image, it should replace user1_pic.jpg with the current uploaded image.
  • Display the image back in the browser using ajax.

I don't want the page to refresh so I'm doing all in ajax. Now, when I upload a file say Image1.jpg then display it on the browser. The problem that I meet now is when I tried to display the newly uploaded image, the old image is the one displayed even though when I look at the physical file, it has already been changed.

The answer I found out is the previous image is being cached by ASP.NET MVC. If your request, any kind of page request, does not change in URL. ASP.NET MVC will give you the cached page instead of the original page.

My scenario is when I displayed the image, the image source URL is not changed, so ASP.NET MVC returns me the cached image URL instead of the original image URL. For example, my image URL is this. http://localhost/MySite/pictures/user1_pic.jpg. And this is requested several times by ajax request, even though my image is changed, ASP.NET MVC will still return the cached URL of the image. So I will see the old image instead of the newly uploaded image.

Solution:
The solution for this problem is so simple. I just need to change the image URL everytime I call an ajax request on success callback by adding a random parameter of the image. e.g. http://localhost/MySite/pictures/user1_pic.jpg?rand=3us9jl. The rand parameter value should always change since I am generating a random character on it.

Friday, October 22, 2010

Create an Operation Sequence Component in Commerce Server 2009

  1. Create a class that inherits OperationSequenceComponent class.
  2. Add the following library in the includes
    • Microsoft.Commerce.Providers.Components;
    • Microsoft.CommerceServer.Runtime.Orders;
    • Microsoft.Commerce.Contracts.Messages;
    • Microsoft.Commerce.Broker;
    • Microsoft.Commerce.Common.MessageBuilders;
    • Microsoft.Commerce.Contracts;
  3. Override one of the following methods inside OperationSequenceComponents
    • ExecuteQuery – Should be override if you intend to Query an Entity.
    • ExecuteCreate – Should be override if you intend to Add a new entry to the Entity.
    • ExecuteUpdate – Should be override if you intend to Update an existing Entity.
    • ExecuteDelete – Should be override if you intend to Delete an existing Entity.
    Each methods has a parameter of CommerceUpdateOperation, OperationCacheDictionary, and CommerceUpdateOperationResponse. Each parameter is self explanatory but I will try to explain.
    CommerceUpdateOperation holds the information of the entity that you want to create, read, update or delete (CRUD). These are the Model information or the searched entity.
    OperationCacheDictionary hold the current information of the Entity you want to create, read, update or delete (CRUD). These information are saved to cache and the data is serialized, and these data will be used in the other OperationSequenceComponent. Either read, or updated.
    CommerceUpdateOperationResponse holds the information you want to return to the calling Method. In Commerce Foundation, you can specify what related model of the Entity you want to return.
  4. If you have completed your class. Add it in the OperationSequence of the right MessageHandler in ChannelConfiguration.config where you want to add your Component. Say if you want to add a Component when you update and Entity for example Basket, the right MessageHandler should be CommerceUpdateOperation_Basket. Each component added in the Operation Sequence is hierarchal . The component that you add should be in a signed library.

Tuesday, October 5, 2010

ASP.MVC JS script source and CSS files not mapped correctly

I've meet a lot of questions regarding why CSS and JS attachments to an ASP.NET MVC page sometimes found in some page but not in other pages specially when you add a 4th segment to your url.

For example, your URL is
http://localhost/Home/Page/Article/1
Certainly, the CSS and javascripts files will not work correctly on this pages since ASP.NET MVC attached those files by default like this.
<script type="text/javascript" language="javascript" src="../../Scripts/jquery-1.4.1.js"></script>
Where it is mapped 2 levels higher of the Scripts folder. So when the parser looks for the included js script from the stated url it will look 2 levels higher only of the last segment which is 1. But your Url has 4 levels or segments which the parser ends up looking at the /Home segment and the actual JS file is in the root of your URL.

My solution for this is to create a base url instead of mapping it with ../../ I would create a helper that will generate a link tag or script tag for my CSS and my javascripts

Helper.cs
public static string GenerateCSSLink(this HtmlHelper helper, string cssPath)

      var request = helper.ViewContext.RequestContext.HttpContext.Request;
      string baseUrl = request.Url.Scheme + "://" + request.Url.Host + (request.Url.Port == 80 ? "" : ":" + request.Url.Port.ToString()) + "/";
      string url;
      if (cssPath.StartsWith("/"))
      {
          url = baseUrl + cssPath.Substring(1);
      }
      else
      {
          url = baseUrl + cssPath;
      }
      string link = "<link href=\"" + url + "\" rel=\"stylesheet\" type=\"text/css\" />";

      return link; 
}

In my Master page where I have included my CSS and Scripts I will import the namespace of my Helper.cs and I can now call
<%=Html.GenerateCSSLink("/Content/Site.css") %>

Tuesday, September 14, 2010

PHP quoted strings

In PHP, I've been wondering what's the difference between single quoted strings and double quoted string. How they differ each other. Doing some research, I've found out that double-quoted strings can have variables in it that is interpreted or parsed by the compiler while single-quoted strings ignores variables in it.

For example,

$name = "John Doe";
echo = 'Hello $name'; // This outputs Hello $name
echo = "Hello $name"; // This outputs Hello John Doe
As you can see, the first echo does not evaluate $name but instead it just displayed it directly. While the second echo evaluates the variable $name and displayed John Doe.


PHP strings
can be specified not just in two ways, but
in four ways.
  1. Single quoted strings will display things almost completely "as is." Variables and most escape sequences will not be interpreted. The exception is that to display a literal single quote, you can escape it with a back slash \', and to display a back slash, you can escape it with another backslash \\ (So yes, even single quoted strings are parsed).
  2. Double quote strings will display a host of escaped characters (including some regexes), and variables in the strings will be evaluated. An important point here is that you can use curly braces to isolate the name of the variable you want evaluated. For example let's say you have the variable $type and you what to echo "The $types are" That will look for the variable
    $types. To get around this use echo "The {$type}s are" You can put the left brace before or after the dollar sign. Take a look at string parsing to see how to use array variables and such.
  3. Heredoc string syntax works like double quoted strings. It starts with <<<. After this operator, an identifier is provided, then a newline. The string itself follows, and then the same identifier again to close the quotation. You don't need to escape quotes in this syntax.
  4. Nowdoc (since PHP 5.3.0) string syntax works essentially like single quoted strings. The difference is that not even single quotes or backslashes have to be escaped. A nowdoc is identified with the same <<< sequence used for heredocs, but the identifier which follows is enclosed in single quotes, e.g. <<<'EOT'. No parsing is done in nowdoc.
Speed:

I would not put too much weight on single quotes being faster than double quotes. They probably are faster in certain situations. Here's an article explaining one manner in which single and double quotes are essentially equally fast since PHP 4.3 (Useless Optimizations toward the bottom, section C). Also, this benchmarks page has a single vs double quote comparison. Most of the comparisons are the same. There is one comparison where double quotes are slower than single quotes.

Source, Stackoverflow

Wednesday, September 8, 2010

ASP.NET MVC: Creating an ImageLink Extension

It come in my way that when creating an ImageLink in ASP.NET MVC, you cannot directly do something like

<%=Html.ActionLink("<img src=\"~/Content/img.png\" width=\"100\" height=\"50\" />", "Index2", "Home") %>

I'll try to explain this why this will not display an image link.  MVC will encode the string you entered in the linkText parameter of the ActionLink so all tags you entered there will be replace by a Url friendly character e.g. < will become %3C so when it this is displayed in the page, it is displayed as a string.

There is a way of using th ActionLink as the same way but you have string replace your linkText like this.

<%=Html.ActionLink("__IMG__", "Index2", "Home").ToString().Replace("__IMG__", "<img src=\"~/Content/img.png\" width=\"100\" height=\"50\" />")%>

which is very long for me.

Here's my way of doing it easily, by creating an Html Extension for ImageLinks

First Create an HtmlHelper file with a static class, you can put it in a Helpers Folder in your MVC Application.  All of your methods should be static.

public static class HtmlUIHelper
{
public static string ImageLink(this HtmlHelper helper, string ImgPath, string altText, string actionName, string controllerName)
{
var imgTagBuilder = new TagBuilder("img");
imgTagBuilder.MergeAttribute("src", ImgPath);
if(!string.IsNullOrEmpty(CssClass))
imgTagBuilder.AddCssClass(CssClass);
imgTagBuilder.MergeAttribute("alt", LinkText);
string imgTag = imgTagBuilder.ToString();

string imgLnk = helper.ActionLink("_TEMP_", actionName, controllerName).ToString().Replace("_TEMP_", imgTag);
return imgLnk;
}
}

You can now call your extension in any View by Importing the Namespace of you class.

<%@ Import Namespace="MvcApplication1.Helpers" %>

And now you can call your Html Extension for an Image Link.

<%=Html.ImageLink("~/Content/img.png", "LinkImageClass", "Cool Stuffs", "CoolStuffs", "Home") %>

This is just a simple link, you can do more with it, you can add more overloads to it just like the ActionLink extension method of the built-in extensions of ASP.NET MVC.

Saturday, September 4, 2010

ASP.NET MVC: Passing Data to Master Page without using ViewData

I've been working with MVC for a while now and my most common problem is when I want to put a Dynamic content on my Master Page depending on the Page that is being displayed. The most common thing to do here is that you don't want to put that Control/PartialView (.ascx) in your MasterPage instead you will create a PartialView and call it in each page that you want to place it with, and unfortunatelly, those pages are all of your pages that are using the MasterPage. So you have to place that control in all of your pages.

This kind of approach is already a very good approach since you will only need to change one PartialView page and this will reflect all of the other Pages that is using that PartialView Page.

Now I've been thinking, what if I can put that in the masterpage so that I can only include it once and only in the masterpage. After surfing around the internet. I found this post in StackOverflow about passing a strongly typed data to the masterpage.

I will try to show here the implementation that I made.

Create a BaseModel for your MasterPage.

First thing is to create a BaseModel class that will be inherited with your MasterPage and this will also be inherited to all of your Pages that is strongly-typed.

public class BaseModel
{
public string ProductIdRelations { get; set; }
}
You should inherit this in your MasterPage views

<%@ Master Language="C#" Inherits="System.Web.Mvc.ViewMasterPage<Namespace.Models.BaseModel>" %>

You should access the Properties of your BaseModel by calling

<%=Model.RelatedProductId %>

Inherit BaseModel to all ViewModels of the pages.

You have to inherit your BaseModel to all of your ViewModels except for those PartialViews.

public class ProductViewModel : BaseModel
{
public ProductModel Product { get; set; }
}

public class ProductModel
{
public string ProductId { get; set; }
public string ProductName { get; set; }
public string ProductDescription { get; set; }
public string ProductImage { get; set; }
}

Now in your Controller,

public class ProductController : Controller
{
ProductRepository prodRepository = new ProductRepository();

public ActionResult Product(int id)
{
ProductModel productModel = prodRepository.GetProduct(id);
ProductViewModel productViewModel = new ProductViewModel();
// you can set here the RelatedProductId of your BaseModel
productViewModel.ProductIdRelations = productModel.ProductId;

return View(productViewModel);
}
}

The View of my Product is inherting the ProductViewModel class

<%@ Page Title="Products" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<NameSpace.Models.ProductViewModel>" %>


In my next post, I will try to enhance this method by injecting IViewDataFactory as discussed in here

Friday, September 3, 2010

Adding jQuery intellisence in your javascript in VS2008

I've been developing Websites in Visual Studio and I am very fond of its intellisence.  Intellisence helps a lot in your skills and most of the time, makes you more productive.  One of the great thing also in VS intellesence is you can create a summary of the public or private method/class you made, where not just by showing it to you the methods/class but also providing you a brief summary of how the method/class works or what is the purpose of the method/class depending on how you or a built-in method is described in your summary.

But when I started to add some javascript codes to my project sometimes I forgot some functions or properties of javascript, specially those in jQuery and the once that I have created so I keep on changing page just to see what are those functions and/or properties.  So I search the web and found out this very helpfull blog of ScuttGu's on jQuery Intellisen in VS 2008

After I have completed the steps on how to Enable jQuery Intellisense in VS 2008.  It works terrific! But only in the same page as where I put my <script> block that calls out the jQuery js file.  Because whe I start coding a separate .js file, the jQuery intellisence is gone so I wonder why the jQuery intellisense will not show in the separate .js file.  And I found out a post of Reference JS file in Other JS File and Intellisence.  It works like a charm. 

So when I want to access an intellisense of jQuery in my Person.js file, I'll just add

/// <reference path="path-to-my-jquery.js" />

at the first line of my Person.js file.  If you want to add more intellisense in your .js file just add the reference path to your other .js file.

And in addition to that.  I've tried to add some summary to my functions and properties that I've created so I can review them without going back to the .js file where I wrote the functions.

Person.ComputeAge = function(yearToday, birthYear) {
    /// <summary>
    ///    Compute the age of the person
    /// </summary>
    /// <param type="Int">Current Year</param>
    /// <param type="Int">Birth Year</param>
   
    ...
    // my code goes here
    ...

}

so when I tried to access Person.ComputeAge() it will display a summary of the function just like the intellisense of Visual Studio.