Archive

Posts Tagged ‘ASP.Net’

Using MemoryCache in .Net 4.0

November 27, 2011 2 comments

Since ASP.Net first came, it came up with a very powerful feature of in-memory object cache (System.Web.Caching.Cache) to store commonly used expensive data on server side. Almost every ASP.Net application/site uses this feature now. But it suffered from few shortcomings like-

  • It is available in ASP.Net only leaving WinForms or WPF clients puzzled.
  • It is not extensible to accommodate other demands to store cache objects in disk or Sql Server. However, MS after realizing these shortcomings, Caching Application Block library was included in its Enterprise Library.
  • .Net developers have to look for their own mechanisms to create logical in-memory partitions called regions to group or organize cache objects in memory.

However, .Net 4.0 came up with a new set of caching APIs in System.Runtime.Caching namespace that addresses all the above shortcomings. This new namespace can be found in System.Runtime.Caching.dll assembly. But this assembly reference is available only target framework of .Net Framework 4, not .Net Framework 4 Client Profile.

The System.Runtime.Caching namespace contains two core set of classes:

  • Concrete implementation of System.Runtime.Caching.MemoryCache class to support in-memory object cache. MemoryCache is closely modeled after old System.Web.Caching.Cache of ASP.Net. However, one does not have to rely upon System.Web assembly to use MemoryCache (We will see it through an example shortly).
  • Abstract types to build custom cache implementation other than in-built MemoryCache.

Now let’s move to try out an example to leverage MemoryCache features. First of all we will create a class library type project. Add a class MyCache and assembly reference of System.Runtime.caching.dll.

MyCache Code sample:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Caching;

namespace DotNetCachingWrapper
{
public enum MyCachePriority
{
Default,
NotRemovable
}

public class MyCache
{
// Gets a reference to the default MemoryCache instance.
private static ObjectCache cache = MemoryCache.Default;
private CacheItemPolicy policy = null;
private CacheEntryRemovedCallback callback = null;

public void AddToMyCache(String CacheKeyName, Object CacheItem, MyCachePriority MyCacheItemPriority, List<String> FilePath)
{
//
callback = new CacheEntryRemovedCallback(this.MyCachedItemRemovedCallback);
policy = new CacheItemPolicy();
policy.Priority = (MyCacheItemPriority == MyCachePriority.Default) ? CacheItemPriority.Default : CacheItemPriority.NotRemovable;
policy.AbsoluteExpiration = DateTimeOffset.Now.AddSeconds(10.00);
policy.RemovedCallback = callback;
policy.ChangeMonitors.Add(new HostFileChangeMonitor(FilePath));

// Add inside cache
cache.Set(CacheKeyName, CacheItem, policy);
}

public Object GetMyCachedItem(String CacheKeyName)
{
//
return cache[CacheKeyName] as Object;
}

public void RemoveMyCachedItem(String CacheKeyName)
{
//
if (cache.Contains(CacheKeyName))
{
cache.Remove(CacheKeyName);
}
}

private void MyCachedItemRemovedCallback(CacheEntryRemovedArguments arguments)
{
// Log these values from arguments list
String strLog = String.Concat("Reason: ", arguments.RemovedReason.ToString(), "
| Key-Name: ", arguments.CacheItem.Key, " | Value-Object: ",
arguments.CacheItem.Value.ToString());
}

}
}

Build this class library to generate assembly name of MyCachingWrapper.dll. Now we are ready to use this library in all ASP.Net web, WinForms and WPF applications.

Now let’s see examples of how this library can be commonly used in both ASP.Net Web Form and WinForm after adding reference of MyCachingWrapper.dll.

ASP.Net Page_Load:

protected void Page_Load(object sender, EventArgs e)
{
//
MyCache objCache = new MyCache();
String strUserName = objCache.GetMyCachedItem("USER_NAME") as String;
if (String.IsNullOrEmpty(strUserName))
{
List<String> lstFiles = new List<string>();
lstFiles.Add(HttpContext.Current.Request.MapPath("~/XmlFiles/ListOfUsers.xml"));

XElement x = XElement.Load(HttpContext.Current.Request.MapPath("~/XmlFiles/ListOfUsers.xml"));
var qry = from u in x.Elements("Users") where u.Element("UserCode").Value == "101" select u;
strUserName = qry.First().Element("UserName").Value;

// Add inside cache
objCache.AddToMyCache("USER_NAME", strUserName, MyCachePriority.Default, lstFiles);
}
this.lblUserName.Text = strUserName;
}

WinForm Form_Load:

private void frmDefault_Load(object sender, EventArgs e)
{
//
MyCache objCache = new MyCache();
String strFilePath =System.IO.Path.Combine(Environment.CurrentDirectory, "../../XmlFiles/ListOfUsers.xml");
String strUserName = objCache.GetMyCachedItem("USER_NAME") as String;
if (String.IsNullOrEmpty(strUserName))
{
List<String> lstFiles = new List<string>();
lstFiles.Add(strFilePath);

XElement x = XElement.Load(strFilePath);
var qry = from u in x.Elements("Users") where u.Element("UserCode").Value == "101" select u;
strUserName = qry.First().Element("UserName").Value;

// Add inside cache
objCache.AddToMyCache("USER_NAME", strUserName, MyCachePriority.Default, lstFiles);
}
this.lblUserName.Text = strUserName;
}

Sample ListOfUsers.xml File:

<?xml version="1.0"?>
<ListOfUsers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance&quot; xmlns:xsd="http://www.w3.org/2001/XMLSchema"&gt;
<Users>
<UserCode>101</UserCode>
<UserName>Dan Brown</UserName>
</Users>
<Users>
<UserCode>102</UserCode>
<UserName>da Vinci</UserName>
</Users>
<Users>
<UserCode>103</UserCode>
<UserName>Monalisa</UserName>
</Users>
<Users>
<UserCode>104</UserCode>
<UserName>Shakespeare</UserName>
</Users>
<Users>
<UserCode>105</UserCode>
<UserName>William Wordsworth</UserName>
</Users>
</ListOfUsers>

Now we can debug above code and see other interesting things. You will see the usage of MemoryCache methods and its techniques to cache objects are similar to what we have been doing in ASP.Net cache so far. Also, we see how the same MyCache library is usable in both web and windows applications.

MemoryCache points worth mentioning:

  • MemoryCache.Default returns the single and same instance of in-memory ObjectCache through a static read-only property.

    public static MemoryCache Default { get; }

  • CacheEntryRemovedCallback signature is different than what we have seen in prior versions of ASP.Net. Refer to example. In the current callback method, one can see the following details when cache item is expired after 10 seconds.

CallbackArgumentsDetails

  • CacheItemPriority enum in .Net 4.0 is cleaner than what we have seen in prior versions of ASP.Net. Now, it is only Default and NotRemovable.
  • In prior version of ASP.Net, CacheDependency was used to monitor changes in any underlying objects like files, Sql database tables, rows, columns, etc. Now .Net 4.0 provides ChangeMonitor class which is ASP.Net neutral and has wider scope of monitoring dependent objects to expire cache items. However, CacheDependency is still there in ASP.Net 4.0. We should use other implementation of ChangeMonitor like HostFileChangeMontor in the above example.
  • The default implementation of MemoryCache does not give us flexibility to add regions along with keys. In order to use regions, you should extend MemoryCache.

Hope you all will appreciate .Net 4.0 caching feature.

Advertisements

ASP.Net 4.0 New Features

ViewStateMode – ViewState for Individual Controls
ASP.Net 4.0 allows view state in a page to be more controllable from page to its child controls level. That is, view state of a control can be enabled or disabled irrespective of its parent control’s view state. Even if view state of a page is disabled, controls of the page can have their own view state individually enabled or disabled or even inherited from the page’s view state mode property.
This property if utilized properly can certainly boost performance of a page.

For example, we can individually enable or disable user control’s view state in a page.

ViewStateMode

By default, ViewStateMode is enabled for a page object, while controls have inherit mode.

Page.MetaKeywords and Page.MetaDescription – SEO Optimization Feature
ASP.Net 4.0 has come up with these two properties that will help developers add meta tags for keywords and description in the aspx pages in easier fashion. Web Search Engines really need these two meta tags for search indexing of any pages. These two properties can be used in a page in various ways. Inside <head> tag or in the code behind or even at <%@Page%> directive level.

However, setting meta keywords or description in code behind will be more useful when we have to add keywords and descriptions dynamically from source like database.

MetaKeyWords is used to store few useful keywords that will briefly highlight important information of a page by tags. From SEO perspective, meta keywords should contain keywords separated by spaces.

MetaDescription is used to add page description in short that will help Search Engines to quickly describe about the page links in search pages.

Prior to ASP.Net 4.0, we have to add meta tags using HtmlMeta control (public class HtmlMeta : HtmlControl) adding into page header as:

protected void Page_Load(object sender, EventArgs e)
{
//
HtmlMeta metakey = new HtmlMeta();
metakey.Name = "keywords";
metakey.Content = "ASP.Net 2.0 3.5";
HtmlMeta metadesc = new HtmlMeta();
metadesc.Name = "description";
metadesc.Content = "ASP.Net 2.0 3.5 Page Description...";
//Add to page header
Page.Header.Controls.Add(metakey);
Page.Header.Controls.Add(metadesc);
}


In ASP.Net 4.0, we can add in many ways.

protected void Page_Load(object sender, EventArgs e)
{
//Adding Page meta tags information
this.Page.MetaKeywords = "ASP.Net 4.0 SEO Meta Tag";
this.Page.MetaDescription = "Serializing and Deserializing Thoughts..";
}

Or,

<head runat="server">
  
<title>Feature: ViewStateMode</title>
<meta name="keywords" content ="ASP.Net 4.0 ViewStateMode"/>
<meta name="description" content="ViewStateMode feature in ASP.Net 4.0" />
</head>

Or inside Page directive,

MetaDescription

Response.RedirectPermanent – Search Engine Friendly Webpage Redirection

In classic ASP or ASP.Net earlier than 4.0, we used to redirect to new pages or links by setting Response.StatusCode to 301 before calling Response.AddHeader method. Now ASP.Net 4.0 has provided Response.RedirectPermanent method to redirect to new pages or links with StatusCode of 301 implicitly set. Search Engines use this 301 code to understand permanent redirection from old pages links.

For example,

Classic ASP method:

<%@ Language=VBScript %>
<%
Response.Status="301 Moved Permanently"
Response.AddHeader "Location","http://www.new-page-url.com/"
%>


ASP.Net method prior to 4.0:

<script runat="server">
private void Page_Load(object sender, System.EventArgs e)
{
Response.Status = "301 Moved Permanently";
Response.AddHeader("Location","http://www.new-page-url.com");
}
</script>


ASP.Net 4.0 method:

Response.RedirectPermanent("http://www.new-page-url.com ");


Web.Config Refactoring – Custom HttpHandlers and HttpModules

Web.config now looks cleaner as most of the settings are controlled from machine.config file as ASP.Net 4.0 is all set to benefit from IIS 7 and IIS 7.5 features. When IIS is set to use .Net 4.0 and Integrated Pipeline mode, <compilation> element holds .Net version attribute. And the traditional <httpHandlers> and <httpModules> section is now shifted out of <system.web> and added inside new section <system.webserver>. All the custom handlers are added inside <handlers>, and all the modules inside <modules> section.

<system.webServer>
<!-- Add the module for Integrated mode applications -->
<modules runAllManagedModulesForAllRequests="true">
<add name="MyModule" type="WebAppModule.MyCustomModule, WebAppModule" />
</modules>
<!-- Add the handler for Integrated mode applications -->
<handlers>
<add name="MyHandler" path="svrtime.tm" verb="GET" 
<type="WebAppModule.MyCustomHandler, WebAppModule"
preCondition="integratedMode" /> </handlers> </system.webServer>


Also,

<system.web>
<compilation debug="true" targetFramework="4.0" />


Interesting point is, when we add custom handlers and modules this way, we do not have to manually configure handlers and modules in IIS again. IIS will automatically refresh itself.

Exception Handling in WCF

We have been doing exception handling in managed application using try-catch block with Exception or its derived Custom Exception objects. But this mechanism is very much .Net Technology specific. When we develop SOA applications, our application is not limited to mere one technology or single loyal client. So the communication process of this service or service method level errors to client via wire becomes a little bit tricky. WCF has two types of error handling mechanism: one is by as usual Exception objects, and other is by SOAP fault message. SOAP fault is used to marshall .Net exceptions to client in much readable and convenient way to support interoperability. With use of SOAP fault, the verbose exception message is reduced to Code and Message. For this System.ServiceModel namespace comes FaultException class and FaultContract attribute.

Let’s come to see from example on how to do exception handling in WCF application. Before this, write our service first.

namespace WcfSvc
{
[ServiceContract]
public interface IBasicMathService
{
[OperationContract]
int Subtraction(int x, int y);

[OperationContract]
int Multiplication(int x, int y);

[OperationContract]
[FaultContract(typeof(BasicMathFault))]
int Addition(int x, int y);
}

[DataContract]
public class BasicMathFault
{
//
[DataMember]
public string Source;

[DataMember]
public string ExceptionMessage;

[DataMember]
public string InnerException;

[DataMember]
public string StackTrace;
}
}

And its implementation is as:

public class BasicMath : IBasicMathService
{
public int Addition(int x, int y)
{
//
int result = 0;
try
{
result = (x + y);
}
catch
{
BasicMathFault ex = new BasicMathFault();
ex.Source = "BasicMath.Addition method";
ex.ExceptionMessage = "Could not perform addition operation.";
ex.InnerException = "Inner exception from math service";
ex.StackTrace = "";
//Throwing strongly-typed FaultException
throw new FaultException(ex, new FaultReason("This is an error condition in BasicMath.Addition method")); }

return result;
}

public int Multiplication(int x, int y)
{
//Due to some calculation error condition, let’s assume we are throwing this error.
//Throwing simply FaultException
throw new FaultException(new FaultReason("Error occurred while processing
for the result"), new FaultCode("mutliplication.method.error"));
}

public int Subtraction(int x, int y)
{
//Exception we generally throw in managed application in the form of Exception object
throw new NotImplementedException("Method still not implemented");
}
}

This is our typical service related code. If we see IBasicMathService interface and its implementation in BasicMath class, we have:

Addition(x,y) method decorated with FaultContract attribute in IBasicMathService class,

Subtraction(x,y) method using simple Exception throwing mechanism,

Multiplication(x,y) method using simple FaultException object, and

Addition(x,y) method using strongly-typed fault of type BasicMathFault in FaultException object

So what does all this mean to client, and how exception is transmitted to client? Let’s answer with these three examples in our client code.

A) Throwing Simple Exception

private void SubtractIntegers()
{
try
{
obj = new BasicmathServiceRef.BasicMathServiceClient();
int result = obj.Subtraction(10, 15);
}
catch (Exception ex)
{
Response.Write(ex.Message + "
");
}
}

When this method is called, client receives verbose error message from WCF as:

“The server was unable to process the request due to an internal error. For more information about the error, either turn on IncludeExceptionDetailInFaults (either from ServiceBehaviorAttribute or from the configuration behavior) on the server in order to send the exception information back to the client, or turn on tracing as per the Microsoft .NET Framework 3.0 SDK documentation and inspect the server trace logs.”

If we closely see this error information, we come across two things: turn on\off IncludeExceptionDetailInFaults value either through ServiceBehaviorAttribute of the class containing this method, or modify IncludeExceptionDetailInFaults value in configuration file or section of this service.

Either of these two things is pretty easy.

a) Decorate BasicMath class as:

[ServiceBehavior(IncludeExceptionDetailInFaults = false)]
public class BasicMath : IBasicMathService
{

b) Or, modify in config file

By default this key value is false. If we make it true, the verbose error message that we received will be reduced to human readable message that we passed in constructor of NotImplementedException.

“Method still not implemented”

While debugging WCF exception, one may encounter error in the service like “xyz exception unhandled by user code”. This is some what misleading, but no need to worry.

B) Throw exception of FaultException type

private void MultiplyIntegers()
{
try
{
obj = new BasicmathServiceRef.BasicMathServiceClient();
int result = obj.Multiplication(10, 15);
}
catch (FaultException ex)
{
Response.Write(ex.Message + "");
}
}

On calling this method, WCF will serialize the exception as a Fault message and return to the client as:

“Error occurred while processing for the result”

However, client is unlikely to receive verbose error message if we throw exception of type FaultException even key IncludeExceptionDetailInFaults is true or false. If we see the exception thrown code,

throw new FaultException(new FaultReason("Error occurred while processing for the result"), new FaultCode("mutliplication.method.error"));

we have used FaultCode. Client can use this specific fault code contained in FaultException code to take decision, but this approach becomes more of procedural by many if-else condition to branch out code some thing like:

if (ex.Code.Name == "mutliplication.method.error")
{
Response.Write(ex.Message + "");
}

C) Throwing with strongly typed fault

private void AddIntegers()
{
try
{
obj = new BasicmathServiceRef.BasicMathServiceClient();
int result = obj.Addition(10, 15);
}
catch (FaultException ex)
{
Response.Write(ex.Message + " ");
}
}

With this approach, client will be able to explicitly handle fault of only that type whose service method is to be used by client. Here, we are using BasicMathFault type. At the service level, the specific method has to be decorated with FaultContract attribute so that exception can be serialized as:

[OperationContract]
[FaultContract(typeof(BasicMathFault))]
int Addition(int x, int y);

The detail of fault type is up to our convenient level to let WCF serialize only needful information to client.

When we call this Addition(x,y) method, one may receive this error message if an exception occurs.

“This is an error condition in BasicMath.Addition method”

Thus, we see how we can do exception handling in WCF.

Calling Method in Parent Page from User Control

October 10, 2009 Leave a comment

In ASP.Net, we develop custom user control as a reusable server control independent of any containing parent aspx page. User control has its own public properties, methods, delegates, etc that can be used by parent aspx page. When a user control is embedded or loaded into a page, the page can access public properties, methods, delegates, etc that are in user control. After loading the user control, there a situation may arise like calling methods in page itself. But when a user control is developed, it has no knowledge of containing page. So it becomes a trick to call the page method.

In .Net, Delegate class has one method DynamicInvoke. DynamicInvoke method is used to invoke (late-bound) method referenced by delegate. We can use this method to call a method in parent page from user control. Let’s try with this example.

First create a user control called CustomUserCtrl. Its code will look some thing like this:

public partial class CustomUserCtrl : System.Web.UI.UserControl
{
private System.Delegate _delWithParam;
public Delegate PageMethodWithParamRef
{
set { _delWithParam = value; }
}

private System.Delegate _delNoParam;
public Delegate PageMethodWithNoParamRef
{
set { _delNoParam = value; }
}

protected void Page_Load(object sender, EventArgs e)
{
}

protected void BtnMethodWithParam_Click(object sender, System.EventArgs e)
{
//Parameter to a method is being made ready
object[] obj = new object[1];
obj[0] = "Parameter Value" as object;
_delWithParam.DynamicInvoke(obj);
}

protected void BtnMethowWithoutParam_Click(object sender, System.EventArgs e)
{
//Invoke a method with no parameter
_delNoParam.DynamicInvoke();
}
}

Then add this user control into an aspx page. The code behind of this page is as:

public partial class _Default : System.Web.UI.Page
{
delegate void DelMethodWithParam(string strParam);
delegate void DelMethodWithoutParam();
protected void Page_Load(object sender, EventArgs e)
{
DelMethodWithParam delParam = new DelMethodWithParam(MethodWithParam);
//Set method reference to a user control delegate
this.UserCtrl.PageMethodWithParamRef = delParam;
DelMethodWithoutParam delNoParam = new DelMethodWithoutParam(MethodWithNoParam);
//Set method reference to a user control delegate
this.UserCtrl.PageMethodWithNoParamRef = delNoParam;
}

private void MethodWithParam(string strParam)
{
Response.Write("<br/>It has parameter: " + strParam);
}

private void MethodWithNoParam()
{
Response.Write("<br/>It has no parameter.");
}
}

BtnMethodWithParam and BtnMethowWithoutParam are two different buttons on the user control that are invoking the methods in the parent page. On Page_Load of the page, we are setting the references of page class methods to delegate type properties in the user control. Click different buttons of user control, you will see MethodWithParam(string strParam) and MethodWithNoParam() methods called.

This is all we have to do to call page class methods from user control in ASP.Net.

Load ASP.Net User Control Dynamically Using jQuery

October 10, 2009 5 comments

Today we will explore the way of loading ASP.Net user control at run time using jQuery. jQuery has one method load(fn) that will help here. This load(fn) method has following definition.

load (url, data, callback): A GET request will be performed by default – but if any extra parameters are passed, then a POST will occur.
url (string): URL of the required page
data (map – key/value pair): key value pair data that will be sent to the server
callback (callback method): call back method, not necessarily success

Now comes custom HttpHandler that will load the required user control from the URL given by this load(fn) method. We all know that it is either in-built or custom HttpHandler that is the end point for any request made in ASP.Net.

Let’s see by example. In the ASP.Net application, add one aspx page and user control. Then, add one more class derived from IHttpHandler. The aspx html markup will look something like this.

<html xmlns=”http://www.w3.org/1999/xhtml&#8221; >
<head runat=”server”>
<title>Load ASP.Net User Control</title>
<script src=”jquery-1.2.6.js”></script>
<script>
$(document).ready(function() {
$(“#BtnLoadUserCtrl”).click(function() {
$(“#UserCtrl”).load(“SampleUserCtrl.ascx”);
});
});
</script>
</head>
<body>
<form runat=”server”>
<div>
<br />
<input value=”Load User Control” /> <br />
<div id=”UserCtrl”></div>
</div>
</form>
</body>
</html>

The code is quite readable. On the click event of BtnLoadUserCtrl button, SampleUserCtrl.ascx user control is being tried to load in the <div> element having id UserCtrl.

Then, write our custom Httphandler called jQueryHandler as below.

public class jQueryHandler:IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
// We add control in Page tree collection
using(var dummyPage = new Page())
{
dummyPage.Controls.Add(GetControl(context));
context.Server.Execute(dummyPage, context.Response.Output, true);
}
}

private Control GetControl(HttpContext context)
{
// URL path given by load(fn) method on click of button
string strPath = context.Request.Url.LocalPath;
UserControl userctrl = null;
using(var dummyPage = new Page())
{
userctrl = dummyPage.LoadControl(strPath) as UserControl;
}
// Loaded user control is returned
return userctrl;
}

public bool IsReusable
{
get { return true; }
}
}

Do not miss to add this HttpHandler in the web.config.

<httpHandlers>
<add verb=”*” path=”*.ascx” type=”JQUserControl.jQueryHandler, JQUserControl”/>
</httpHandlers>

This web.config configuration tells that jQueryHandler will process request for file type having .ascx extension and methods all (GET, POST, etc). The type attribute value is something like:
type=”Namespace.TypeName, Assembly name where Handler can be found”

Now we are ready to test our sample. Run the page, and see on the click of button, the sampleusertCtrl.ascx is loaded.

I hope we can now extend this concept to fit any such programming requirement in future.
Happy Coding!

CacheItemRemovedCallback Example in ASP.Net

September 20, 2009 Leave a comment

Notify When an Item is Removed from Cache in ASP.Net

While adding or inserting an item into cache object, we add dependency object as well to ensure the cache is automatically invalidated if any change is detected in that dependent object like file, for example. Then, we again read or update that item from the original source to make sure the item is still fresh with data. This is one of the main reasons that really appeal the use of ASP.Net caching feature where one can decide about dependencies and expiry time policy. There are other properties also that can be used in combination to set the scope of cached object within time frame and location. See also HttpCacheability .

But today we will explore the CacheItemRemovedCallback delegate provided by ASP.Net. It is used to notify the application about cache removal or deletion with some reason. CacheItemRemovedReason enumeration is used as a parameter in call back method to tell the appropriate reason of removal.

Let’s take an example to know more about the CacheItemRemovedCallback delegate.

protected void Page_Load(object sender, EventArgs e)
{
//Fetch item list from cache
ArrayList cacheditems = CachedItemList();
}

private static CacheItemRemovedCallback OnCachedItemRemoved = null;
private ArrayList CachedItemList()
{
//
OnCachedItemRemoved = new CacheItemRemovedCallback(this.CachedItemRemovedCallback);
ArrayList cacheditems = HttpContext.Current.Cache.Get("CACHE_KEY") as ArrayList;

// Found in cache
if (cacheditems != null)
{
return cacheditems;
}
else
{
// Not found in cache
cacheditems = ItemList();
HttpContext.Current.Cache.Insert("CACHE_KEY", cacheditems, new System.Web.Caching.CacheDependency(Server.MapPath("~//CacheDependentFile.txt")), Cache.NoAbsoluteExpiration, Cache.NoSlidingExpiration, CacheItemPriority.Default, OnCachedItemRemoved);

return cacheditems;
}
}

private void CachedItemRemovedCallback(string key, Object val, CacheItemRemovedReason reason)
{
//
if (reason == CacheItemRemovedReason.DependencyChanged)
{
// Log the cache key name, reason and time details
// when the cached object was removed from the cache

}
}

private ArrayList ItemList()
{
//
ArrayList lst = new ArrayList();
lst.Add("First Item");
lst.Add("Second Item");
lst.Add("Third Item");
lst.Add("Fourth Item");
lst.Add("Fifth Item");
return lst;
}

Let’s see carefully this call back method:

private void CachedItemRemovedCallback(string key, Object val, CacheItemRemovedReason reason)
{
//

}

The first parameter specifies the cache key name that we used to store an item (an ArrayList collection values). Second parameter is the object that we stored in the cache. The third parameter is an enumeration which has enum values like Removed, Expired, Underused, and DependencyChanged.

In the above example, if any change is made in CacheDependentFile.txt file, the call back method is automatically fired, and the reason captured will be DependencyChanged. Try and see.

Important Point: When using a CacheItemRemovedCallback make sure that you make the callback method ("OnCachedItemRemoved " in the sample above) a static method.

This feature can be used in many cases like logging the reason why any cached item was removed from the cache, and many others depending upon the scenario.

jQuery, JSON and ASP.Net Web Service

Today we will see a simple example of jQuery, JSON and ASP.Net Web Service. We will mainly see how to consume ASP.Net web service web methods using both jQuery and JavaScript and see how to handle DateTime object result. Also, how jQuery can be used to call a web method by passing arguments values.

We know JSON type lacks Date/Time literal because JavaScript too does not have Date/Time literal directly. I think JavaScript author was smart enough to leave Date/Time literal! As Date/Time is a complex subject, that should be better left for programmers who write code to interact with servers that have different running time zones, and we know JavaScript is a client-side scripting language.

Let’s see how to handle this with examples. Write a simple web service as shown below.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Services;
using System.Xml.Serialization;
using System.Web.Script.Services;
using System.Web.Script.Serialization;
namespace JsonAndScriptSvc
{
/// <summary>
/// Summary description for WebServerDate
/// </summary>
[WebService(Namespace = “http://tempuri.org/&#8221;)]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.ComponentModel.ToolboxItem(false)]
// To allow this Web Service to be called from script,
// using ASP.NET AJAX, uncomment the following line.
[System.Web.Script.Services.ScriptService]
public class WebServerDate : System.Web.Services.WebService
{
//
private JsonDateSez objJson = null;
public WebServerDate()
{
objJson = new JsonDateSez();
}
[WebMethod]
public object GetServerDate()
{
JavaScriptSerializer serz = new JavaScriptSerializer();
return serz.Serialize(objJson);
}
[WebMethod]
public Int32 GetSumResult(Int32 xValue, Int32 yValue)
{
return (xValue + yValue);
}
}

public class JsonDateSez
{
public DateTime JsonSerzDate
{
get { return new DateTime(2009, 9, 17); }
}
}
}

Then, add one Default.aspx page whose mark-up code looks like this:

<%@ Page Language=”C#” AutoEventWireup=”true” CodeBehind=”Default.aspx.cs” Inherits=”JsonAndScriptSvc._Default” %>
<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN” “http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”&gt;
<html xmlns=”http://www.w3.org/1999/xhtml&#8221; >
<head runat=”server”>
<title>JavaScript and JavaScriptSerializer</title>
<script type=”text/javascript” language=”javascript” src=”JSWebService.js”></script>
</head>
<body>
<form id=”frmJson” runat=”server”>
<asp:ScriptManager ID=”ScriptManager1″ runat=”server” EnablePageMethods=”true”>
<Services>
<asp:ServiceReference Path=”~/WebServerDate.asmx” />
</Services>
</asp:ScriptManager>
<div>
<input id=”BtnFetchDate” type=”button” value=”Check Server Date” onclick=”ServerDate();”/>
<br />
</div>
</form>
</body>
</html>

The onClick() event of BtnFetchDate button will call ServerDate() method in JSWebService.js file. This js file has two methods as:

function ServerDate() {
JsonAndScriptSvc.WebServerDate.GetServerDate(ReceivedDate);
}
function ReceivedDate(result) {
var svrdt = Sys.Serialization.JavaScriptSerializer.deserialize(result);
alert(“Result in Json Format: ” + result + “\n” + “Result desired: ” + svrdt.JsonSerzDate);
}

Once clicked, we may see result as shown in figure below.

JSON-WebService

We saw how JavaScriptSerializer class helped to get the desired date-time result.

Similarly, we can see jQuery based example similar to above one. Let’s add another JQryPage.aspx page whose mark-up may look like this:

<%@ Page Language=”C#” AutoEventWireup=”true” CodeBehind=”JQryPage.aspx.cs” Inherits=”JsonAndScriptSvc.JQryPage” %>
<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN” “http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”&gt;
<html xmlns=”http://www.w3.org/1999/xhtml&#8221; >
<head runat=”server”>
<title>JQuery and Web Service</title>
<script type=”text/javascript” language=”javascript” src=”jquery-1.2.3.min.js” />
<script type=”text/javascript” language=”javascript” src=”JSWebService.js”></script>
<script type=”text/javascript” language=”javascript”>
/* jQuery calling webmethod to fetch server date-time values */
function JQueryWebMethod() {
$.ajax({
type: “POST”,
url: “WebServerDate.asmx/GetServerDate”,
data: “{}”,
contentType: “application/json;charset=utf-8”,
dataType: “json”,
success: function(result) {
alert(“Result in Json Format: ” + result.d);
},
error: function(request, status, throwerror) {
alert(status);
}
});
}
/* jQuery calling webmethod by passing two arguments */
function JQuerySumResultWebMethod() {
$.ajax({
type: “POST”,
url: “WebServerDate.asmx/GetSumResult”,
data: “{‘xValue’:’10’,’yValue’:’15’}”,
contentType: “application/json;charset=utf-8”,
dataType: “json”,
success: function(result) {
alert(result.d);
},
error: function(request, status, throwerror) {
alert(status);
}
});
}
</script>
</head>
<body>
<form id=”form1″ runat=”server”>
<asp:ScriptManager ID=”ScriptManager1″ runat=”server” EnablePageMethods=”true”>
<Services>
<asp:ServiceReference Path=”~/WebServerDate.asmx” />
</Services>
</asp:ScriptManager>
<div>
<input id=”BtnJQry” type=”button” value=”jQry Check Server Date” onclick=”JQueryWebMethod();”/>
<br /><br />
<input id=”BtnSumResult” type=”button” value=”jQry Sum Result” onclick=”JQuerySumResultWebMethod();”/>
</div>
</form>
</body>
</html>

Run this page, click BtnJQry button to see the result of Date/Time. We may see the same raw result that we received in JavaScript before deserializing ‘result’ object using JavaScriptSerializer class. Click other button called BtnSumResult will get the sum result from web method by passing two arguments values.

The documentation of $.ajax() global method can be found at http://docs.jquery.com/Ajax/jQuery.ajax. However, we should remember type, url, data, contentType and dataType key values when constructing parameters for $.ajax() global method.

Thus, we saw jQuery, JSON and ASP.Net Web Service example.