<?xml version='1.0' encoding='UTF-8'?><rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearchrss/1.0/" xmlns:blogger="http://schemas.google.com/blogger/2008" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" version="2.0"><channel><atom:id>tag:blogger.com,1999:blog-2977499297091575918</atom:id><lastBuildDate>Wed, 11 Sep 2024 19:54:24 +0000</lastBuildDate><title>SCRIPTSTER. East Java Baker</title><description>I am just copy content in my bookmark in this blog :)</description><link>http://scriptster.blogspot.com/</link><managingEditor>noreply@blogger.com (Octopus)</managingEditor><generator>Blogger</generator><openSearch:totalResults>98</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><item><guid isPermaLink="false">tag:blogger.com,1999:blog-2977499297091575918.post-6240145289037016917</guid><pubDate>Mon, 17 Dec 2007 03:54:00 +0000</pubDate><atom:updated>2007-12-16T19:57:29.891-08:00</atom:updated><title>Building a Community Site - It&#39;s About People, Not Technology</title><description>&lt;p&gt;            &lt;span id=&quot;dnn_ctr407_rdmview__ctl2_lblDescription&quot; class=&quot;rdmdesc&quot;&gt;Sometimes in the online world when approaching a project people seem to classify the issues facing a website as a technology issue. It&#39;s as if building a web site is this mysterious thing wrapped in so much technology it&#39;s just too much handle. Just sitting in the office of a technology provider gets nerve wracking; hearing all the techno geeks spitting out acronym after acronym and having no idea what any of it means - html, Ajax, XML, HTTP, Java, ASP, .NET, Web services, Web 2.0, what all does it mean?!&lt;!--&lt;rdf:rdf rdf=&quot;http://www.w3.org/1999/02/22-rdf-syntax-ns#&quot; dc=&quot;http://purl.org/dc/elements/1.1/&quot; trackback=&quot;http://madskills.com/public/xml/rss/module/trackback/&quot;&gt;&lt;rdf:description about=&quot;http://www.wwwcoder.com/Default.aspx?tabid=68&amp;mid=407&amp;ctl=Trackback&amp;id=6522&quot; identifier=&quot;http://www.wwwcoder.com/Default.aspx?tabid=68&amp;mid=407&amp;ctl=Trackback&amp;id=6522&quot; title=&quot;WWWCoder.com&quot; ping=&quot;http://www.wwwcoder.com/Default.aspx?tabid=68&amp;mid=407&amp;ctl=Trackback&amp;id=6522&quot;&gt;&lt;/rdf:RDF&gt;--&gt;  &lt;/span&gt;&lt;/p&gt;           &lt;span id=&quot;dnn_ctr407_rdmview__ctl2__ctl0_lblAds&quot;&gt;Sometimes in the online world when approaching a project people seem to classify the issues facing a website as a technology issue. It&#39;s as if building a web site is this mysterious thing wrapped in so much technology it&#39;s just too much handle. Just sitting in the office of a technology provider gets nerve wracking; hearing all the techno geeks spitting out acronym after acronym and having no idea what any of it means - html, Ajax, XML, HTTP, Java, ASP, .NET, Web services, Web 2.0, what all does it mean?! &lt;/span&gt;&lt;p&gt;&lt;/p&gt; &lt;p align=&quot;left&quot;&gt;I&#39;m here to tell you not to worry about all those acronyms, phrases, and geeks telling you what to do, do what you know. Websites are nothing but a different way of doing your business; bricks and mortar are the traditional way, but they both have something in common and that&#39;s people. In this article I&#39;m going to discuss community sites since they&#39;re a growing influence on the web and generating plenty of interest. &lt;/p&gt;&lt;p align=&quot;left&quot;&gt;Community; what do you think of when you hear community? Think of community as your own home town. Anyone who&#39;s played Sim City should have some concept of what it takes to build a community. If you remember from the game, you had some cash to build houses, roads, and services. Now let&#39;s look at that on the web, you have some money to build a site, network connection to the Internet, and some functionality to the site. The site is your community and to build it, you need to provide some place for people to live. &lt;/p&gt;&lt;p align=&quot;left&quot;&gt;In the beginning in order to grow your community you have to provide a place for your users to live. Granted a site that is mostly static is nice to visit, but I wouldn&#39;t want to live there (sound familiar?). You have to provide something on your site to encourage people to want to live there. There are the usual features like forums, weblogs, profile pages and the like, that&#39;s a good start, it gives a person a place to live. &lt;/p&gt;&lt;p align=&quot;left&quot;&gt;When you add these &quot;living spaces&quot; for your users, consider what they provide, at a minimum they should provide your user community with the ability to express themselves. As in any community whether offline or online people want to express themselves and distinguish themselves from others in the crowd. They build this identity by the clothes they wear, cars they drive, and people they associate with. Online they do something similar; they create avatars, profiles to help them connect with others that have similar interests. And just like in the physical communities people go to churches, community activities, and other places to develop relationships with people that have similar interests. They&#39;ll do the same on your website, but you need to provide them with a means to do. So when shopping for interactive applications ensure that they will provide mechanisms for your users to build those relationships. &lt;/p&gt;&lt;p align=&quot;left&quot;&gt;As a community grows it needs leadership and this is the same online. For example, if your site becomes popular and has forums, usually you&#39;ll see a few of your posters become pretty prominate in their activity, posting frequently. By providing them with moderator privileges or some special designation you allow leaders to step up, and provide the community with people who appear to have some connection to the site and help build community and participation. You could extend the moderator concept to enable your users to host online chats, or even participate in podcasts or weblog posts. &lt;/p&gt;&lt;p align=&quot;left&quot;&gt;As time goes by your site leaders will come and go, and it will be up to you to monitor activity within the site and find leaders. This further enhances the community aspect and allows your community to be dynamic. &lt;/p&gt;&lt;p align=&quot;left&quot;&gt;Another thing to foster growth and participation is to have periodic contests, contests that allow for some user contributed content is ideal. For example some sites have users submit stories, graphics like humorous graphics, basically anything that builds content for your site, but still enables your population to contribute to the site. The cost is relatively low, and if you have the traffic you may be able to work relationships with sponsors to provide the spoils to the winner. &lt;/p&gt;&lt;p align=&quot;left&quot;&gt;The main idea to take from this article is community sites are not about technology, they&#39;re about people. Find out what people like and enable them to &quot;own&quot; your site. If you do this your site is sure to grow and prosper. Good luck! &lt;/p&gt; &lt;p align=&quot;left&quot;&gt;Patrick Santry, owner of WWWCoder.com. Is an MVP, and has over 13 years in web and eBusiness strategy. His current position is a Solution Architect for the &lt;a href=&quot;http://www.bluechip-llc.com/&quot; target=&quot;_blank&quot;&gt;Blue Chip Consulting Group, LLC.&lt;/a&gt; in Cleveland, OH.&lt;/p&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;octopus east java baker&lt;/div&gt;</description><link>http://scriptster.blogspot.com/2007/12/building-community-site-its-about.html</link><author>noreply@blogger.com (Octopus)</author><thr:total>1</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-2977499297091575918.post-5931070287891470700</guid><pubDate>Mon, 17 Dec 2007 03:52:00 +0000</pubDate><atom:updated>2007-12-16T19:54:26.870-08:00</atom:updated><title>URL Rewriting in ASP.NET</title><description>&lt;p&gt;Scott Mitchell&lt;br /&gt;4GuysFromRolla.com&lt;/p&gt;&lt;b&gt;&lt;/b&gt;&lt;br /&gt;&lt;h2 class=&quot;dtH1&quot;&gt;&lt;a name=&quot;urlrewriting_topic1&quot;&gt;&lt;!----&gt;&lt;/a&gt;Introduction&lt;/h2&gt; &lt;p&gt;Take a moment to look at some of the URLs on your website. Do you find URLs like http://yoursite.com/info/dispEmployeeInfo.aspx?EmpID=459-099&amp;amp;type=summary? Or maybe you have a bunch of Web pages that were moved from one directory or website to another, resulting in broken links for visitors who have bookmarked the old URLs. In this article we&#39;ll look at using &lt;i&gt;URL rewriting&lt;/i&gt; to shorten those ugly URLs to meaningful, memorable ones, by replacing http://yoursite.com/info/dispEmployeeInfo.aspx?EmpID=459-099&amp;amp;type=summary with something like http://yoursite.com/people/sales/chuck.smith. We&#39;ll also see how URL rewriting can be used to create an intelligent 404 error.&lt;/p&gt; &lt;p&gt;URL rewriting is the process of intercepting an incoming Web request and redirecting the request to a different resource. When performing URL rewriting, typically the URL being requested is checked and, based on its value, the request is redirected to a different URL. For example, in the case where a website restructuring caused all of the Web pages in the /people/ directory to be moved to a /info/employees/ directory, you would want to use URL rewriting to check if a Web request was intended for a file in the /people/ directory. If the request was for a file in the /people/ directory, you&#39;d want to automatically redirect the request to the same file, but in the /info/employees/ directory instead.&lt;/p&gt; &lt;p&gt;With classic ASP, the only way to utilize URL rewriting was to write an ISAPI filter or to buy a third-party product that offered URL rewriting capabilities. With Microsoft® ASP.NET, however, you can easily create your own URL rewriting software in a number of ways. In this article we&#39;ll examine the techniques available to ASP.NET developers for implementing URL rewriting, and then turn to some real-world uses of URL rewriting. Before we delve into the technological specifics of URL rewriting, let&#39;s first take a look at some everyday scenarios where URL rewriting can be employed.&lt;/p&gt; &lt;h2 class=&quot;dtH1&quot;&gt;&lt;a name=&quot;urlrewriting_topic2&quot;&gt;&lt;!----&gt;&lt;/a&gt;Common Uses of URL Rewriting&lt;/h2&gt; &lt;p&gt;Creating data-driven ASP.NET websites often results in a single Web page that displays a subset of the database&#39;s data based on querystring parameters. For example, in designing an e-commerce site, one of your tasks would be to allow users to browse through the products for sale. To facilitate this, you might create a page called displayCategory.aspx that would display the products for a given category. The category&#39;s products to view would be specified by a querystring parameter. That is, if the user wanted to browse the Widgets for sale, and all Widgets had a had a CategoryID of 5, the user would visit: http://yousite.com/displayCategory.aspx?CategoryID=5.&lt;/p&gt; &lt;p&gt;There are two downsides to creating a website with such URLs. First, from the end user&#39;s perspective, the URL http://yousite.com/displayCategory.aspx?CategoryID=5 is a mess. Usability expert &lt;a onclick=&quot;javascript:Track(&#39;ctl00_rs1_mainContentContainer_ctl00|ctl00_rs1_mainContentContainer_ctl03&#39;,this);&quot; href=&quot;http://useit.com/&quot;&gt;Jakob Neilsen&lt;/a&gt; &lt;a onclick=&quot;javascript:Track(&#39;ctl00_rs1_mainContentContainer_ctl00|ctl00_rs1_mainContentContainer_ctl04&#39;,this);&quot; href=&quot;http://www.useit.com/alertbox/990321.html&quot;&gt;recommends&lt;/a&gt; that URLs be chosen so that they:  &lt;/p&gt;&lt;ul type=&quot;disc&quot;&gt;&lt;li&gt;Are short.&lt;/li&gt;&lt;li&gt;Are easy to type.&lt;/li&gt;&lt;li&gt;Visualize the site structure.&lt;/li&gt;&lt;li&gt;&quot;Hackable,&quot; allowing the user to navigate through the site by hacking off parts of the URL.&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;I would add to that list that URLs should also be easy to remember. The URL http://yousite.com/displayCategory.aspx?CategoryID=5 meets none of Neilsen&#39;s criteria, nor is it easy to remember. Asking users to type in querystring values makes a URL hard to type and makes the URL &quot;hackable&quot; only by experienced Web developers who have an understanding of the purpose of querystring parameters and their name/value pair structure. &lt;/p&gt; &lt;p&gt;A better approach is to allow for a sensible, memorable URL, such as http://yoursite.com/products/Widgets. By just looking at the URL you can infer what will be displayed—information about Widgets. The URL is easy to remember and share, too. I can tell my colleague, &quot;Check out yoursite.com/products/Widgets,&quot; and she&#39;ll likely be able to bring up the page without needing to ask me again what the URL was. (Try doing that with, say, an Amazon.com page!) The URL also appears, and should behave, &quot;hackable.&quot; That is, if the user hacks of the end of the URL, and types in http://yoursite.com/products, they should see a listing of &lt;i&gt;all&lt;/i&gt; products, or at least a listing of all categories of products they can view.&lt;/p&gt; &lt;p&gt;&lt;b class=&quot;le&quot;&gt;Note   &lt;/b&gt;For a prime example of a &quot;hackable&quot; URL, consider the URLs generated by many blog engines. To view the posts for January 28, 2004, one visits a URL like http://someblog.com/2004/01/28. If the URL is hacked down to http://someblog.com/2004/01, the user will see all posts for January 2004. Cutting it down further to http://someblog.com/2004 will display all posts for the year 2004.&lt;/p&gt; &lt;p&gt;In addition to simplifying URLs, URL rewriting is also often used to handle website restructuring that would otherwise result in numerous broken links and outdated bookmarks.&lt;/p&gt; &lt;h2 class=&quot;dtH1&quot;&gt;&lt;a name=&quot;urlrewriting_topic3&quot;&gt;&lt;!----&gt;&lt;/a&gt;What Happens When a Request Reaches IIS&lt;/h2&gt; &lt;p&gt;Before we examine exactly how to implement URL rewriting, it&#39;s important that we have an understanding of how incoming requests are handled by Microsoft® Internet Information Services (IIS). When a request arrives at an IIS Web server, IIS examines the requested file&#39;s extension to determine how handle the request. Requests can be handled natively by IIS—as are HTML pages, images, and other static content—or IIS can route the request to an ISAPI extension. (An ISAPI extension is an unmanaged, compiled class that handles an incoming Web request. Its task is to generate the content for the requested resource.)&lt;/p&gt; &lt;p&gt;For example, if a request comes in for a Web page named Info.asp, IIS will route the message to the asp.dll ISAPI extension. This ISAPI extension will then load the requested ASP page, execute it, and return its rendered HTML to IIS, which will then send it back to the requesting client. For ASP.NET pages, IIS routes the message to the aspnet_isapi.dll ISAPI extension. The aspnet_isapi.dll ISAPI extension then hands off processing to the managed ASP.NET worker process, which processes the request, returning the ASP.NET Web page&#39;s rendered HTML.&lt;/p&gt; &lt;p&gt;You can customize IIS to specify what extensions are mapped to what ISAPI extensions. Figure 1 shows the Application Configuration dialog box from the Internet Information Services Administrative Tool. Note that the ASP.NET-related extensions—.aspx, .ascx, .config, .asmx, .rem, .cs, .vb, and others—are all mapped to the aspnet_isapi.dll ISAPI extension.&lt;/p&gt; &lt;p class=&quot;fig&quot;&gt;&lt;img alt=&quot;&quot; src=&quot;http://msdn2.microsoft.com/en-us/library/ms972974.urlrewriting_fig01%28en-us,MSDN.10%29.gif&quot; border=&quot;0&quot; /&gt;&lt;/p&gt; &lt;p class=&quot;label&quot;&gt; &lt;/p&gt;&lt;p class=&quot;normal&quot;&gt; &lt;/p&gt;&lt;p class=&quot;label&quot;&gt;&lt;b&gt;Figure 1. Configured mappings for file extensions&lt;/b&gt;&lt;/p&gt; &lt;p&gt;A thorough discussion of how IIS manages incoming requests is a bit beyond the scope of this article. A great, in-depth discussion, though, can be found in Michele Leroux Bustamante&#39;s article &lt;a onclick=&quot;javascript:Track(&#39;ctl00_rs1_mainContentContainer_ctl00|ctl00_rs1_mainContentContainer_ctl05&#39;,this);&quot; href=&quot;http://www.theserverside.net/articles/showarticle.tss?id=IIS_ASP&quot;&gt;Inside IIS and ASP.NET&lt;/a&gt;. It&#39;s important to understand that the ASP.NET engine gets its hands only on incoming Web requests whose extensions are explicitly mapped to the aspnet_isapi.dll in IIS.&lt;/p&gt; &lt;h3 class=&quot;dtH1&quot;&gt;Examining Requests with ISAPI Filters&lt;/h3&gt; &lt;p&gt;In addition to mapping the incoming Web request&#39;s file extension to the appropriate ISAPI extension, IIS also performs a number of other tasks. For example, IIS attempts to authenticate the user making the request and determine if the authenticated user has authorization to access the requested file. During the lifetime of handling a request, IIS passes through several states. At each state, IIS raises an event that can be programmatically handled using ISAPI filters.&lt;/p&gt; &lt;p&gt;Like ISAPI extensions, ISAPI filters are blocks of unmanaged code installed on the Web server. ISAPI extensions are designed to generate the response for a request to a particular file type. ISAPI filters, on the other hand, contain code to respond to events raised by IIS. ISAPI filters can intercept and even modify the incoming and outgoing data. ISAPI filters have numerous applications, including: &lt;/p&gt;&lt;ul type=&quot;disc&quot;&gt;&lt;li&gt;Authentication and authorization.&lt;/li&gt;&lt;li&gt;Logging and monitoring.&lt;/li&gt;&lt;li&gt;HTTP compression.&lt;/li&gt;&lt;li&gt;URL rewriting.&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;While ISAPI filters can be used to perform URL rewriting, this article examines implementing URL rewriting using ASP.NET. However, we will discuss the tradeoffs between implementing URL rewriting as an ISAPI filter versus using techniques available in ASP.NET.&lt;/p&gt; &lt;h3 class=&quot;dtH1&quot;&gt;What Happens When a Request Enters the ASP.NET Engine&lt;/h3&gt; &lt;p&gt;Prior to ASP.NET, URL rewriting on IIS Web servers needed to be implemented using an ISAPI filter. URL rewriting is possible with ASP.NET because the ASP.NET engine is strikingly similar to IIS. The similarities arise because the ASP.NET engine: &lt;/p&gt;&lt;ol type=&quot;1&quot;&gt;&lt;li&gt;Raises events as it processes a request.&lt;/li&gt;&lt;li&gt;Allows an arbitrary number of &lt;i&gt;HTTP modules&lt;/i&gt; handle the events that are raised, akin to IIS&#39;s ISAPI filters.&lt;/li&gt;&lt;li&gt;Delegates rendering the requested resource to an &lt;i&gt;HTTP handler&lt;/i&gt;, which is akin to IIS&#39;s ISAPI extensions.&lt;/li&gt;&lt;/ol&gt; &lt;p&gt;Like IIS, during the lifetime of a request the ASP.NET engine fires events signaling its change from one state of processing to another. The &lt;b&gt;BeginRequest&lt;/b&gt; event, for example, is fired when the ASP.NET engine first responds to a request. The &lt;b&gt;AuthenticateRequest&lt;/b&gt; event fires next, which occurs when the identity of the user has been established. (There are numerous other events—&lt;b&gt;AuthorizeRequest&lt;/b&gt;, &lt;b&gt;ResolveRequestCache&lt;/b&gt;, and &lt;b&gt;EndRequest&lt;/b&gt;, among others. These events are events of the &lt;b&gt;System.Web.HttpApplication&lt;/b&gt; class; for more information consult the &lt;a onclick=&quot;javascript:Track(&#39;ctl00_rs1_mainContentContainer_ctl00|ctl00_rs1_mainContentContainer_ctl06&#39;,this);&quot; href=&quot;http://msdn2.microsoft.com/en-us/library/4wt3wttw.aspx&quot;&gt;HttpApplication Class Overview&lt;/a&gt; technical documentation.)&lt;/p&gt; &lt;p&gt;As we discussed in the previous section, ISAPI filters can be created to respond to the events raised by IIS. In a similar vein, ASP.NET provides &lt;i&gt;HTTP modules&lt;/i&gt; that can respond to the events raised by the ASP.NET engine. An ASP.NET Web application can be configured to have multiple HTTP modules. For each request processed by the ASP.NET engine, each configured HTTP module is initialized and allowed to wire up event handlers to the events raised during the processing of the request. Realize that there are a number of built-in HTTP modules utilized on each an every request. One of the built-in HTTP modules is the &lt;b&gt;FormsAuthenticationModule&lt;/b&gt;, which first checks to see if forms authentication is being used and, if so, whether the user is authenticated or not. If not, the user is automatically redirected to the specified logon page.&lt;/p&gt; &lt;p&gt;Recall that with IIS, an incoming request is eventually directed to an ISAPI extension, whose job it is to return the data for the particular request. For example, when a request for a classic ASP Web page arrives, IIS hands off the request to the asp.dll ISAPI extension, whose task it is to return the HTML markup for the requested ASP page. The ASP.NET engine utilizes a similar approach. After initializing the HTTP modules, the ASP.NET engine&#39;s next task is to determine what &lt;i&gt;HTTP handler&lt;/i&gt; should process the request. &lt;/p&gt; &lt;p&gt;All requests that pass through the ASP.NET engine eventually arrive at an HTTP handler or an HTTP handler factory (an HTTP handler factory simply returns an instance of an HTTP handler that is then used to process the request). The final HTTP handler renders the requested resource, returning the response. This response is sent back to IIS, which then returns it to the user that made the request.&lt;/p&gt; &lt;p&gt;ASP.NET includes a number of built-in HTTP handlers. The &lt;b&gt;PageHandlerFactory&lt;/b&gt;, for example, is used to render ASP.NET Web pages. The &lt;b&gt;WebServiceHandlerFactory&lt;/b&gt; is used to render the response SOAP envelopes for ASP.NET Web services. The &lt;b&gt;TraceHandler&lt;/b&gt; renders the HTML markup for requests to &lt;b&gt;trace.axd&lt;/b&gt;.&lt;/p&gt; &lt;p&gt;Figure 2 illustrates how a request for an ASP.NET resource is handled. First, IIS receives the request and dispatches it to aspnet_isapi.dll. Next, the ASP.NET engine initializes the configured HTTP modules. Finally, the proper HTTP handler is invoked and the requested resource is rendered, returning the generated markup back to IIS and back to the requesting client.&lt;/p&gt; &lt;p class=&quot;fig&quot;&gt;&lt;img alt=&quot;&quot; src=&quot;http://msdn2.microsoft.com/en-us/library/ms972974.urlrewriting_fig02%28en-us,MSDN.10%29.gif&quot; border=&quot;0&quot; /&gt;&lt;/p&gt; &lt;p class=&quot;label&quot;&gt; &lt;/p&gt;&lt;p class=&quot;normal&quot;&gt; &lt;/p&gt;&lt;p class=&quot;label&quot;&gt;&lt;b&gt;Figure 2. Request processing by IIS and ASP.NET&lt;/b&gt;&lt;/p&gt; &lt;h3 class=&quot;dtH1&quot;&gt;Creating and Registering Custom HTTP Modules and HTTP Handlers&lt;/h3&gt; &lt;p&gt;Creating custom HTTP modules and HTTP handlers are relatively simple tasks, which involve created a managed class that implements the correct interface. HTTP modules must implement the &lt;b&gt;System.Web.IHttpModule&lt;/b&gt; interface, while HTTP handlers and HTTP handler factories must implement the &lt;b&gt;System.Web.IHttpHandler&lt;/b&gt; interface and &lt;b&gt;System.Web.IHttpHandlerFactory&lt;/b&gt; interface, respectively. The specifics of creating HTTP handlers and HTTP modules is beyond the scope of this article. For a good background, read Mansoor Ahmed Siddiqui&#39;s article, &lt;a onclick=&quot;javascript:Track(&#39;ctl00_rs1_mainContentContainer_ctl00|ctl00_rs1_mainContentContainer_ctl07&#39;,this);&quot; href=&quot;http://www.15seconds.com/issue/020417.htm&quot;&gt;HTTP Handlers and HTTP Modules in ASP.NET&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;Once a custom HTTP module or HTTP handler has been created, it must be registered with the Web application. Registering HTTP modules and HTTP handlers for an entire Web server requires only a simple addition to the machine.config file; registering an HTTP module or HTTP handler for a specific Web application involves adding a few lines of XML to the application&#39;s Web.config file.&lt;/p&gt; &lt;p&gt;Specifically, to add an HTTP module to a Web application, add the following lines in the Web.config&#39;s configuration/system.web section:&lt;/p&gt; &lt;div class=&quot;code&quot; id=&quot;ctl00_rs1_mainContentContainer_ctl08_&quot;&gt;&lt;pre class=&quot;code&quot; id=&quot;ctl00_rs1_mainContentContainer_ctl08&quot; space=&quot;preserve&quot;&gt;&lt;httpmodules&gt;&lt;br /&gt;  &lt;add type=&quot;type&quot; name=&quot;name&quot;&gt;&lt;br /&gt;&lt;/httpmodules&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt; &lt;p&gt;The &lt;i&gt;type&lt;/i&gt; value provides the assembly and class name of the HTTP module, whereas the &lt;i&gt;name&lt;/i&gt; value provides a friendly name by which the HTTP module can be referred to in the Global.asax file.&lt;/p&gt; &lt;p&gt;HTTP handlers and HTTP handler factories are configured by the &lt;httphandlers&gt; tag in the Web.config&#39;s configuration/system.web section, like so:&lt;/p&gt; &lt;div class=&quot;code&quot; id=&quot;ctl00_rs1_mainContentContainer_ctl09_&quot;&gt;&lt;pre class=&quot;code&quot; id=&quot;ctl00_rs1_mainContentContainer_ctl09&quot; space=&quot;preserve&quot;&gt;&lt;httphandlers&gt;&lt;br /&gt;  &lt;add verb=&quot;verb&quot; path=&quot;path&quot; type=&quot;type&quot;&gt;&lt;br /&gt;&lt;/httphandlers&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt; &lt;p&gt;Recall that for each incoming request, the ASP.NET engine determines what HTTP handler should be used to render the request. This decision is made based on the incoming requests verb and path. The verb specifies what type of HTTP request was made—GET or POST—whereas the path specifies the location and filename of the file requested. So, if we wanted to have an HTTP handler handle all requests—either GET or POST—for files with the .scott extension, we&#39;d add the following to the Web.config file:&lt;/p&gt; &lt;div class=&quot;code&quot; id=&quot;ctl00_rs1_mainContentContainer_ctl10_&quot;&gt;&lt;pre class=&quot;code&quot; id=&quot;ctl00_rs1_mainContentContainer_ctl10&quot; space=&quot;preserve&quot;&gt;&lt;httphandlers&gt;&lt;br /&gt;  &lt;add verb=&quot;*&quot; path=&quot;*.scott&quot; type=&quot;type&quot;&gt;&lt;br /&gt;&lt;/httphandlers&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt; &lt;p&gt;where &lt;i&gt;type&lt;/i&gt; was the type of our HTTP handler.&lt;/p&gt; &lt;blockquote class=&quot;dtBlock&quot;&gt; &lt;b class=&quot;le&quot;&gt;Note   &lt;/b&gt;When registering HTTP handlers, it is important to ensure that the extensions used by the HTTP handler are mapped in IIS to the ASP.NET engine. That is, in our .scott example, if the .scott extension is not mapped in IIS to the aspnet_isapi.dll ISAPI extension, a request for the file foo.scott will result in IIS attempting to return the contents of the file foo.scott. In order for the HTTP handler to process this request, the .scott extension must be mapped to the ASP.NET engine. The ASP.NET engine, then, will route the request correctly to the appropriate HTTP handler.&lt;/blockquote&gt; &lt;p&gt;For more information on registering HTTP modules and HTTP handlers, be sure to consult the &lt;a onclick=&quot;javascript:Track(&#39;ctl00_rs1_mainContentContainer_ctl00|ctl00_rs1_mainContentContainer_ctl11&#39;,this);&quot; href=&quot;http://msdn2.microsoft.com/en-us/library/9b9dh535.aspx&quot;&gt;&lt;httpmodules&gt; element documentation&lt;/a&gt; along with the &lt;a onclick=&quot;javascript:Track(&#39;ctl00_rs1_mainContentContainer_ctl00|ctl00_rs1_mainContentContainer_ctl12&#39;,this);&quot; href=&quot;http://msdn2.microsoft.com/en-us/library/aa903367.aspx&quot;&gt;&lt;httphandlers&gt; element documentation&lt;/a&gt;.&lt;/p&gt; &lt;h2 class=&quot;dtH1&quot;&gt;&lt;a name=&quot;urlrewriting_topic4&quot;&gt;&lt;!----&gt;&lt;/a&gt;Implementing URL Rewriting &lt;/h2&gt; &lt;p&gt;URL rewriting can be implemented either with ISAPI filters at the IIS Web server level, or with either HTTP modules or HTTP handlers at the ASP.NET level. This article focuses on implementing URL rewriting with ASP.NET, so we won&#39;t be delving into the specifics of implementing URL rewriting with ISAPI filters. There are, however, numerous third-party ISAPI filters available for URL rewriting, such as: &lt;/p&gt;&lt;ul type=&quot;disc&quot;&gt;&lt;li&gt;&lt;a onclick=&quot;javascript:Track(&#39;ctl00_rs1_mainContentContainer_ctl00|ctl00_rs1_mainContentContainer_ctl13&#39;,this);&quot; href=&quot;http://www.isapirewrite.com/&quot;&gt;ISAPI Rewrite&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a onclick=&quot;javascript:Track(&#39;ctl00_rs1_mainContentContainer_ctl00|ctl00_rs1_mainContentContainer_ctl14&#39;,this);&quot; href=&quot;http://www.qwerksoft.com/products/iisrewrite/&quot;&gt;IIS Rewrite&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a onclick=&quot;javascript:Track(&#39;ctl00_rs1_mainContentContainer_ctl00|ctl00_rs1_mainContentContainer_ctl15&#39;,this);&quot; href=&quot;http://port80software.com/products/pagexchanger/&quot;&gt;PageXChanger&lt;/a&gt;&lt;/li&gt;&lt;li&gt;And many others!&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Implementing URL rewriting at the ASP.NET level is possible through the &lt;b&gt;System.Web.HttpContext&lt;/b&gt; class&#39;s &lt;b&gt;RewritePath()&lt;/b&gt; method. The &lt;b&gt;HttpContext&lt;/b&gt; class contains HTTP-specific information about a specific HTTP request. With each request received by the ASP.NET engine, an &lt;b&gt;HttpContext&lt;/b&gt; instance is created for that request. This class has properties like: &lt;b&gt;Request&lt;/b&gt; and &lt;b&gt;Response&lt;/b&gt;, which provide access to the incoming request and outgoing response; &lt;b&gt;Application&lt;/b&gt; and &lt;b&gt;Session&lt;/b&gt;, which provide access to application and session variables; &lt;b&gt;User&lt;/b&gt;, which provides information about the authenticated user; and other related properties. &lt;/p&gt; &lt;p&gt;With the Microsoft® .NET Framework Version 1.0, the &lt;b&gt;RewritePath()&lt;/b&gt; method accepts a single string, the new path to use. Internally, the &lt;b&gt;HttpContext&lt;/b&gt; class&#39;s &lt;b&gt;RewritePath(string)&lt;/b&gt; method updates the &lt;b&gt;Request&lt;/b&gt; object&#39;s &lt;b&gt;Path&lt;/b&gt; and &lt;b&gt;QueryString&lt;/b&gt; properties. In addition to &lt;b&gt;RewritePath(string)&lt;/b&gt;, the .NET Framework Version 1.1 includes another form of the &lt;b&gt;RewritePath()&lt;/b&gt; method, one that accepts three string input parameters. This alternate overloaded form not only sets the &lt;b&gt;Request&lt;/b&gt; object&#39;s &lt;b&gt;Path&lt;/b&gt; and &lt;b&gt;QueryString&lt;/b&gt; properties, but also sets internal member variables that are used to compute the &lt;b&gt;Request&lt;/b&gt; object&#39;s values for its &lt;b&gt;PhysicalPath&lt;/b&gt;, &lt;b&gt;PathInfo&lt;/b&gt;, and &lt;b&gt;FilePath&lt;/b&gt; properties.&lt;/p&gt; &lt;p&gt;To implement URL rewriting in ASP.NET, then, we need to create an HTTP module or HTTP handler that:  &lt;/p&gt;&lt;ol type=&quot;1&quot;&gt;&lt;li&gt;Checks the requested path to determine if the URL needs to be rewritten.&lt;/li&gt;&lt;li&gt;Rewrites the path, if needed, by calling the &lt;b&gt;RewritePath()&lt;/b&gt; method.&lt;/li&gt;&lt;/ol&gt; &lt;p&gt;For example, imagine that our website had information each employee, accessible through /info/employee.aspx?empID=employeeID. To make the URLs more &quot;hackable,&quot; we might decide to have employee pages accessible by: /people/EmployeeName.aspx. Here is a case where we&#39;d want to use URL rewriting. That is, when the page /people/ScottMitchell.aspx was requested, we&#39;d want to rewrite the URL so that the page /info/employee.aspx?empID=1001 was used instead.&lt;/p&gt; &lt;h3 class=&quot;dtH1&quot;&gt;URL Rewriting with HTTP Modules&lt;/h3&gt; &lt;p&gt;When performing URL rewriting at the ASP.NET level you can use either an HTTP module or an HTTP handler to perform the rewriting. When using an HTTP module, you must decide at what point during the request&#39;s lifecycle to check to see if the URL needs to be rewritten. At first glance, this may seem to be an arbitrary choice, but the decision can impact your application in both significant and subtle ways. The choice of where to perform the rewrite matters because the built-in ASP.NET HTTP modules use the &lt;b&gt;Request&lt;/b&gt; object&#39;s properties to perform their duties. (Recall that rewriting the path alters the &lt;b&gt;Request&lt;/b&gt; object&#39;s property values.) These germane built-in HTTP modules and the events they tie into are listed below:&lt;/p&gt; &lt;div class=&quot;tablediv&quot;&gt;&lt;table class=&quot;dtTABLE&quot;&gt; &lt;tbody&gt;&lt;tr valign=&quot;top&quot;&gt; &lt;td width=&quot;40%&quot;&gt;&lt;b&gt;HTTP Module&lt;/b&gt;&lt;/td&gt; &lt;td width=&quot;28%&quot;&gt;&lt;b&gt;Event&lt;/b&gt;&lt;/td&gt; &lt;td width=&quot;32%&quot;&gt;&lt;b&gt;Description&lt;/b&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr valign=&quot;top&quot;&gt; &lt;td width=&quot;40%&quot;&gt;&lt;b&gt;FormsAuthenticationModule&lt;/b&gt;&lt;/td&gt; &lt;td width=&quot;28%&quot;&gt;&lt;b&gt;AuthenticateRequest&lt;/b&gt;&lt;/td&gt; &lt;td width=&quot;32%&quot;&gt;Determines if the user is authenticated using forms authentication. If not, the user is automatically redirected to the specified logon page.&lt;/td&gt; &lt;/tr&gt; &lt;tr valign=&quot;top&quot;&gt; &lt;td width=&quot;40%&quot;&gt;&lt;b&gt;FileAuthorizationMoudle&lt;/b&gt;&lt;/td&gt; &lt;td width=&quot;28%&quot;&gt;&lt;b&gt;AuthorizeRequest&lt;/b&gt;&lt;/td&gt; &lt;td width=&quot;32%&quot;&gt;When using Windows authentication, this HTTP module checks to ensure that the Microsoft® Windows® account has adequate rights for the resource requested.&lt;/td&gt; &lt;/tr&gt; &lt;tr valign=&quot;top&quot;&gt; &lt;td width=&quot;40%&quot;&gt;&lt;b&gt;UrlAuthorizationModule&lt;/b&gt;&lt;/td&gt; &lt;td width=&quot;28%&quot;&gt;&lt;b&gt;AuthorizeRequest&lt;/b&gt;&lt;/td&gt; &lt;td width=&quot;32%&quot;&gt;Checks to make sure the requestor can access the specified URL. URL authorization is specified through the &lt;authorization&gt; and &lt;location&gt; elements in the Web.config file.&lt;/td&gt; &lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt; &lt;p&gt;Recall that the &lt;b&gt;BeginRequest&lt;/b&gt; event fires before &lt;b&gt;AuthenticateRequest&lt;/b&gt;, which fires before &lt;b&gt;AuthorizeRequest&lt;/b&gt;. &lt;/p&gt; &lt;p&gt;One safe place that URL rewriting can be performed is in the &lt;b&gt;BeginRequest&lt;/b&gt; event. That means that if the URL needs to be rewritten, it will have done so by the time any of the built-in HTTP modules run. The downside to this approach arises when using forms authentication. If you&#39;ve used forms authentication before, you know that when the user visits a restricted resource, they are automatically redirected to a specified login page. After successfully logging in, the user is sent back to the page they attempted to access in the first place. &lt;/p&gt; &lt;p&gt;If URL rewriting is performed in the &lt;b&gt;BeginRequest&lt;/b&gt; or &lt;b&gt;AuthenticateRequest &lt;/b&gt;events, the login page will, when submitted, redirect the user to the rewritten page. That is, imagine that a user types into their browser window, /people/ScottMitchell.aspx, which is rewritten to /info/employee.aspx?empID=1001. If the Web application is configured to use forms authentication, when the user first visits /people/ScottMitchell.aspx, first the URL will be rewritten to /info/employee.aspx?empID=1001; next, the &lt;b&gt;FormsAuthenticationModule&lt;/b&gt; will run, redirecting the user to the login page, if needed. The URL the user will be sent to upon successfully logging in, however, will be /info/employee.aspx?empID=1001, since that was the URL of the request when the &lt;b&gt;FormsAuthenticationModule&lt;/b&gt; ran.&lt;/p&gt; &lt;p&gt;Similarly, when performing rewriting in the &lt;b&gt;BeginRequest&lt;/b&gt; or &lt;b&gt;AuthenticateRequest&lt;/b&gt; events, the &lt;b&gt;UrlAuthorizationModule&lt;/b&gt; sees the rewritten URL. That means that if you use &lt;location&gt; elements in your Web.config file to specify authorization for specific URLs, you will have to refer to the rewritten URL.&lt;/p&gt; &lt;p&gt;To fix these subtleties, you might decide to perform the URL rewriting in the &lt;b&gt;AuthorizeRequest&lt;/b&gt; event. While this approach fixes the URL authorization and forms authentication anomalies, it introduces a new wrinkle: file authorization no longer works. When using Windows authentication, the &lt;b&gt;FileAuthorizationModule&lt;/b&gt; checks to make sure that the authenticated user has the appropriate access rights to access the specific ASP.NET page.&lt;/p&gt; &lt;p&gt;Imagine if a set of users does not have Windows-level file access to C:\Inetput\wwwroot\info\employee.aspx; if such users attempt to visit /info/employee.aspx?empID=1001, then they will get an authorization error. However, if we move the URL rewriting to the &lt;b&gt;AuthenticateRequest&lt;/b&gt; event, when the &lt;b&gt;FileAuthorizationModule&lt;/b&gt; checks the security settings, it still thinks the file being requested is /people/ScottMitchell.aspx, since the URL has yet to be rewritten. Therefore, the file authorization check will pass, allowing this user to view the content of the rewritten URL, /info/employee.aspx?empID=1001.&lt;/p&gt; &lt;p&gt;So, when should URL rewriting be performed in an HTTP module? It depends on what type of authentication you&#39;re employing. If you&#39;re not using any authentication, then it doesn&#39;t matter if URL rewriting happens in &lt;b&gt;BeginRequest&lt;/b&gt;, &lt;b&gt;AuthenticateRequest&lt;/b&gt;, or &lt;b&gt;AuthorizeRequest&lt;/b&gt;. If you are using forms authentication and are not using Windows authentication, place the URL rewriting in the &lt;b&gt;AuthorizeRequest&lt;/b&gt; event handler. Finally, if you are using Windows authentication, schedule the URL rewriting during the &lt;b&gt;BeginRequest&lt;/b&gt; or &lt;b&gt;AuthenticateRequest&lt;/b&gt; events.&lt;/p&gt; &lt;h3 class=&quot;dtH1&quot;&gt;URL Rewriting in HTTP Handlers&lt;/h3&gt; &lt;p&gt;URL rewriting can also be performed by an HTTP handler or HTTP handler factory. Recall that an HTTP handler is a class responsible for generating the content for a specific type of request; an HTTP handler factory is a class responsible for returning an instance of an HTTP handler that can generate the content for a specific type of request.&lt;/p&gt; &lt;p&gt;In this article we&#39;ll look at creating a URL rewriting HTTP handler factory for ASP.NET Web pages. HTTP handler factories must implement the &lt;b&gt;IHttpHandlerFactory&lt;/b&gt; interface, which includes a &lt;b&gt;GetHandler()&lt;/b&gt; method. After initializing the appropriate HTTP modules, the ASP.NET engine determines what HTTP handler or HTTP handler factory to invoke for the given request. If an HTTP handler factory is to be invoked, the ASP.NET engine calls that HTTP handler factory&#39;s &lt;b&gt;GetHandler()&lt;/b&gt; method passing in the &lt;b&gt;HttpContext&lt;/b&gt; for the Web request, along with some other information. The HTTP handler factory, then, must return an object that implements &lt;b&gt;IHttpHandler&lt;/b&gt; that can handle the request.&lt;/p&gt; &lt;p&gt;To perform URL rewriting through an HTTP handler, we can create an HTTP handler factory whose &lt;b&gt;GetHandler()&lt;/b&gt; method checks the requested path to determine if it needs to be rewritten. If it does, it can call the passed-in &lt;b&gt;HttpContext&lt;/b&gt; object&#39;s &lt;b&gt;RewritePath()&lt;/b&gt; method, as discussed earlier. Finally, the HTTP handler factory can return the HTTP handler returned by the &lt;b&gt;System.Web.UI.PageParser&lt;/b&gt; class&#39;s &lt;b&gt;GetCompiledPageInstance()&lt;/b&gt; method. (This is the same technique by which the built-in ASP.NET Web page HTTP handler factory, &lt;b&gt;PageHandlerFactory&lt;/b&gt;, works.)&lt;/p&gt; &lt;p&gt;Since all of the HTTP modules will have been initialized prior to the custom HTTP handler factory being instantiated, using an HTTP handler factory presents the same challenges when placing the URL rewriting in the latter stages of the events—namely, file authorization will not work. So, if you rely on Windows authentication and file authorization, you will want to use the HTTP module approach for URL rewriting.&lt;/p&gt; &lt;p&gt;Over the next section we&#39;ll look at building a reusable URL rewriting engine. Following our examination of the URL rewriting engine—which is available in this article&#39;s code download—we&#39;ll spend the remaining two sections examining real-world uses of URL rewriting. First we&#39;ll look at how to use the URL rewriting engine and look at a simple URL rewriting example. Following that, we&#39;ll utilize the power of the rewriting engine&#39;s regular expression capabilities to provide truly &quot;hackable&quot; URLs.&lt;/p&gt; &lt;h2 class=&quot;dtH1&quot;&gt;&lt;a name=&quot;urlrewriting_topic5&quot;&gt;&lt;!----&gt;&lt;/a&gt;Building a URL Rewriting Engine&lt;/h2&gt; &lt;p&gt;To help illustrate how to implement URL rewriting in an ASP.NET Web application, I created a URL rewriting engine. This rewriting engine provides the following functionality: &lt;/p&gt;&lt;ul type=&quot;disc&quot;&gt;&lt;li&gt;The ASP.NET page developer utilizing the URL rewriting engine can specify the rewriting rules in the Web.config file.&lt;/li&gt;&lt;li&gt;The rewriting rules can use regular expressions to allow for powerful rewriting rules.&lt;/li&gt;&lt;li&gt;URL rewriting can be easily configured to use an HTTP module or an HTTP handler.&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;In this article we will examine URL rewriting with just the HTTP module. To see how HTTP handlers can be used to perform URL rewriting, consult the code available for download with this article.&lt;/p&gt; &lt;h3 class=&quot;dtH1&quot;&gt;Specifying Configuration Information for the URL Rewriting Engine&lt;/h3&gt; &lt;p&gt;Let&#39;s examine the structure of the rewrite rules in the Web.config file. First, you&#39;ll need to indicate in the Web.config file if you want perform URL rewriting with the HTTP module or the HTTP handler. In the download, the Web.config file contains two entries that have been commented out:&lt;/p&gt; &lt;div class=&quot;code&quot; id=&quot;ctl00_rs1_mainContentContainer_ctl16_&quot;&gt;&lt;pre class=&quot;code&quot; id=&quot;ctl00_rs1_mainContentContainer_ctl16&quot; space=&quot;preserve&quot;&gt;&lt;!--&lt;br /&gt;&lt;httpmodules&gt;&lt;br /&gt;  &lt;add type=&quot;URLRewriter.ModuleRewriter, URLRewriter&quot;&lt;br /&gt;       name=&quot;ModuleRewriter&quot; /&gt;&lt;br /&gt;&lt;/httpmodules&gt;&lt;br /&gt;--&gt;&lt;br /&gt;&lt;br /&gt;&lt;!--&lt;br /&gt;&lt;httphandlers&gt;&lt;br /&gt;  &lt;add verb=&quot;*&quot; path=&quot;*.aspx&quot;&lt;br /&gt;       type=&quot;URLRewriter.RewriterFactoryHandler, URLRewriter&quot; /&gt;&lt;br /&gt;&lt;/httphandlers&gt;&lt;br /&gt;--&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt; &lt;p&gt;Comment out the &lt;httpmodules&gt; entry to use the HTTP module for rewriting; comment out the &lt;httphandlers&gt; entry instead to use the HTTP handler for rewriting.&lt;/p&gt; &lt;p&gt;In addition to specifying whether the HTTP module or HTTP handler is used for rewriting, the Web.config file contains the rewriting rules. A rewriting rule is composed of two strings: the pattern to look for in the requested URL, and the string to replace the pattern with, if found. This information is expressed in the Web.config file using the following syntax:&lt;/p&gt; &lt;div class=&quot;code&quot; id=&quot;ctl00_rs1_mainContentContainer_ctl17_&quot;&gt;&lt;pre class=&quot;code&quot; id=&quot;ctl00_rs1_mainContentContainer_ctl17&quot; space=&quot;preserve&quot;&gt;&lt;rewriterconfig&gt;&lt;br /&gt;  &lt;rules&gt;&lt;br /&gt;  &lt;rewriterrule&gt;&lt;br /&gt;     &lt;lookfor&gt;pattern to look for&lt;/lookfor&gt;&lt;br /&gt;     &lt;sendto&gt;string to replace pattern with&lt;/sendto&gt;&lt;br /&gt;  &lt;/rewriterrule&gt;&lt;br /&gt;  &lt;rewriterrule&gt;&lt;br /&gt;     &lt;lookfor&gt;pattern to look for&lt;/lookfor&gt;&lt;br /&gt;     &lt;sendto&gt;string to replace pattern with&lt;/sendto&gt;&lt;br /&gt;  &lt;/rewriterrule&gt;&lt;br /&gt;  ...&lt;br /&gt;  &lt;/rules&gt;&lt;br /&gt;&lt;/rewriterconfig&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt; &lt;p&gt;Each rewrite rule is expressed by a &lt;b&gt;&lt;rewriterrule&gt;&lt;/b&gt; element. The pattern to search for is specified by the &lt;b&gt;&lt;lookfor&gt;&lt;/b&gt; element, while the string to replace the found pattern with is entered in the &lt;b&gt;&lt;sentto&gt;&lt;/b&gt; element. These rewrite rules are evaluated from top to bottom. If a match is found, the URL is rewritten and the search through the rewriting rules terminates.&lt;/p&gt; &lt;p&gt;When specifying patterns in the &lt;b&gt;&lt;lookfor&gt;&lt;/b&gt; element, realize that regular expressions are used to perform the matching and string replacement. (In a bit we&#39;ll look at a real-world example that illustrates how to search for a pattern using regular expressions.) Since the pattern is a regular expression, be sure to escape any characters that are reserved characters in regular expressions. (Some of the regular expression reserved characters include: ., ?, ^, $, and others. These can be escaped by being preceded with a backslash, like \. to match a literal period.)&lt;/p&gt; &lt;h3 class=&quot;dtH1&quot;&gt;URL Rewriting with an HTTP Module&lt;/h3&gt; &lt;p&gt;Creating an HTTP module is as simple as creating a class that implements the &lt;b&gt;IHttpModule&lt;/b&gt; interface. The &lt;b&gt;IHttpModule&lt;/b&gt; interface defines two methods:  &lt;/p&gt;&lt;ul type=&quot;disc&quot;&gt;&lt;li&gt;&lt;b&gt;Init(HttpApplication)&lt;/b&gt;. This method fires when the HTTP module is initialized. In this method you&#39;ll wire up event handlers to the appropriate &lt;b&gt;HttpApplication&lt;/b&gt; events.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Dispose()&lt;/b&gt;. This method is invoked when the request has completed and been sent back to IIS. Any final cleanup should be performed here.&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;To facilitate creating an HTTP module for URL rewriting, I started by creating an abstract base class, &lt;b&gt;BaseModuleRewriter&lt;/b&gt;. This class implements &lt;b&gt;IHttpModule&lt;/b&gt;. In the &lt;b&gt;Init()&lt;/b&gt; event, it wires up the &lt;b&gt;HttpApplication&lt;/b&gt;&#39;s &lt;b&gt;AuthorizeRequest&lt;/b&gt; event to the &lt;b&gt;BaseModuleRewriter_AuthorizeRequest&lt;/b&gt; method. The &lt;b&gt;BaseModuleRewriter_AuthorizeRequest&lt;/b&gt; method calls the class&#39;s &lt;b&gt;Rewrite()&lt;/b&gt; method passing in the requested &lt;b&gt;Path&lt;/b&gt; along with the &lt;b&gt;HttpApplication&lt;/b&gt; object that was passed into the &lt;b&gt;Init()&lt;/b&gt; method. The &lt;b&gt;Rewrite()&lt;/b&gt; method is abstract, meaning that in the &lt;b&gt;BaseModuleRewriter&lt;/b&gt; class, the &lt;b&gt;Rewrite()&lt;/b&gt; method has no method body; rather, the class being derived from &lt;b&gt;BaseModuleRewriter&lt;/b&gt; &lt;i&gt;must&lt;/i&gt; override this method and provide a method body.&lt;/p&gt; &lt;p&gt;With this base class in place, all we have to do now is to create a class derived from &lt;b&gt;BaseModuleRewriter&lt;/b&gt; that overrides &lt;b&gt;Rewrite()&lt;/b&gt; and performs the URL rewriting logic there. The code for &lt;b&gt;BaseModuleRewriter&lt;/b&gt; is shown below.&lt;/p&gt; &lt;div class=&quot;code&quot; id=&quot;ctl00_rs1_mainContentContainer_ctl18_&quot;&gt;&lt;pre class=&quot;code&quot; id=&quot;ctl00_rs1_mainContentContainer_ctl18&quot; space=&quot;preserve&quot;&gt;public abstract class BaseModuleRewriter : IHttpModule&lt;br /&gt;{&lt;br /&gt;  public virtual void Init(HttpApplication app)&lt;br /&gt;  {&lt;br /&gt;     // WARNING!  This does not work with Windows authentication!&lt;br /&gt;     // If you are using Windows authentication,&lt;br /&gt;     // change to app.BeginRequest&lt;br /&gt;     app.AuthorizeRequest += new&lt;br /&gt;        EventHandler(this.BaseModuleRewriter_AuthorizeRequest);&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  public virtual void Dispose() {}&lt;br /&gt;&lt;br /&gt;  protected virtual void BaseModuleRewriter_AuthorizeRequest(&lt;br /&gt;    object sender, EventArgs e)&lt;br /&gt;  {&lt;br /&gt;     HttpApplication app = (HttpApplication) sender;&lt;br /&gt;     Rewrite(app.Request.Path, app);&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  protected abstract void Rewrite(string requestedPath,&lt;br /&gt;    HttpApplication app);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt; &lt;p&gt;Notice that the &lt;b&gt;BaseModuleRewriter&lt;/b&gt; class performs URL rewriting in the &lt;b&gt;AuthorizeRequest&lt;/b&gt; event. Recall that if you use Windows authentication with file authorization, you will need to change this so that URL rewriting is performed in either the &lt;b&gt;BeginRequest&lt;/b&gt; or &lt;b&gt;AuthenticateRequest&lt;/b&gt; events.&lt;/p&gt; &lt;p&gt;The &lt;b&gt;ModuleRewriter&lt;/b&gt; class extends the &lt;b&gt;BaseModuleRewriter&lt;/b&gt; class and is responsible for performing the actual URL rewriting. &lt;b&gt;ModuleRewriter&lt;/b&gt; contains a single overridden method—&lt;b&gt;Rewrite()&lt;/b&gt;—which is shown below:&lt;/p&gt; &lt;div class=&quot;code&quot; id=&quot;ctl00_rs1_mainContentContainer_ctl19_&quot;&gt;&lt;pre class=&quot;code&quot; id=&quot;ctl00_rs1_mainContentContainer_ctl19&quot; space=&quot;preserve&quot;&gt;protected override void Rewrite(string requestedPath,&lt;br /&gt;  System.Web.HttpApplication app)&lt;br /&gt;{&lt;br /&gt;  // get the configuration rules&lt;br /&gt;  RewriterRuleCollection rules =&lt;br /&gt;    RewriterConfiguration.GetConfig().Rules;&lt;br /&gt;&lt;br /&gt;  // iterate through each rule...&lt;br /&gt;  for(int i = 0; i &lt; rules.Count; i++)&lt;br /&gt;  {&lt;br /&gt;     // get the pattern to look for, and&lt;br /&gt;     // Resolve the Url (convert ~ into the appropriate directory)&lt;br /&gt;     string lookFor = &quot;^&quot; +&lt;br /&gt;       RewriterUtils.ResolveUrl(app.Context.Request.ApplicationPath,&lt;br /&gt;       rules[i].LookFor) + &quot;$&quot;;&lt;br /&gt;&lt;br /&gt;     // Create a regex (note that IgnoreCase is set...)&lt;br /&gt;     Regex re = new Regex(lookFor, RegexOptions.IgnoreCase);&lt;br /&gt;&lt;br /&gt;     // See if a match is found&lt;br /&gt;     if (re.IsMatch(requestedPath))&lt;br /&gt;     {&lt;br /&gt;        // match found - do any replacement needed&lt;br /&gt;        string sendToUrl =&lt;br /&gt;RewriterUtils.ResolveUrl(app.Context.Request.ApplicationPath,&lt;br /&gt;           re.Replace(requestedPath, rules[i].SendTo));&lt;br /&gt;&lt;br /&gt;        // Rewrite the URL&lt;br /&gt;        RewriterUtils.RewriteUrl(app.Context, sendToUrl);&lt;br /&gt;        break;      // exit the for loop&lt;br /&gt;     }&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt; &lt;p&gt;The &lt;b&gt;Rewrite()&lt;/b&gt; method starts with getting the set of rewriting rules from the Web.config file. It then iterates through the rewrite rules one at a time, and for each rule, it grabs its &lt;b&gt;LookFor&lt;/b&gt; property and uses a regular expression to determine if a match is found in the requested URL.&lt;/p&gt; &lt;p&gt;If a match is found, a regular expression replace is performed on the requested path with the value of the &lt;b&gt;SendTo&lt;/b&gt; property. This replaced URL is then passed into the &lt;b&gt;RewriterUtils.RewriteUrl()&lt;/b&gt; method. &lt;b&gt;RewriterUtils&lt;/b&gt; is a helper class that provides a couple of static methods used by both the URL rewriting HTTP module and HTTP handler. The &lt;b&gt;RewriterUrl()&lt;/b&gt; method simply calls the &lt;b&gt;HttpContext&lt;/b&gt; object&#39;s &lt;b&gt;RewriteUrl()&lt;/b&gt; method.&lt;/p&gt; &lt;blockquote class=&quot;dtBlock&quot;&gt; &lt;b class=&quot;le&quot;&gt;Note   &lt;/b&gt;You may have noticed that when performing the regular expression match and replacement, a call to &lt;b&gt;RewriterUtils.ResolveUrl()&lt;/b&gt; is made. This helper method simply replaces any instances of &lt;b&gt;~&lt;/b&gt; in the string with the value of the application&#39;s path.&lt;/blockquote&gt; &lt;p&gt;The entire code for the URL rewriting engine is available for download with this article. We&#39;ve examined the most germane pieces, but there are other components as well, such as classes for deserializing the XML-formatted rewriting rules in the Web.config file into an object, as well as the HTTP handler factory for URL rewriting. The remaining three sections of this article examine real-world uses of URL rewriting.&lt;/p&gt; &lt;h2 class=&quot;dtH1&quot;&gt;&lt;a name=&quot;urlrewriting_topic6&quot;&gt;&lt;!----&gt;&lt;/a&gt;Performing Simple URL Rewriting with the URL Rewriting Engine&lt;/h2&gt; &lt;p&gt;To demonstrate the URL rewriting engine in action, let&#39;s build an ASP.NET Web application that utilizes simple URL rewriting. Imagine that we work for a company that sells assorted products online. These products are broken down into the following categories:&lt;/p&gt; &lt;div class=&quot;tablediv&quot;&gt;&lt;table class=&quot;dtTABLE&quot;&gt; &lt;tbody&gt;&lt;tr valign=&quot;top&quot;&gt; &lt;td width=&quot;36%&quot;&gt;&lt;b&gt;Category ID&lt;/b&gt;&lt;/td&gt; &lt;td width=&quot;64%&quot;&gt;&lt;b&gt;Category Name&lt;/b&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr valign=&quot;top&quot;&gt; &lt;td width=&quot;36%&quot;&gt;&lt;b&gt;1&lt;/b&gt;&lt;/td&gt; &lt;td width=&quot;64%&quot;&gt;Beverages&lt;/td&gt; &lt;/tr&gt; &lt;tr valign=&quot;top&quot;&gt; &lt;td width=&quot;36%&quot;&gt;&lt;b&gt;2&lt;/b&gt;&lt;/td&gt; &lt;td width=&quot;64%&quot;&gt;Condiments&lt;/td&gt; &lt;/tr&gt; &lt;tr valign=&quot;top&quot;&gt; &lt;td width=&quot;36%&quot;&gt;&lt;b&gt;3&lt;/b&gt;&lt;/td&gt; &lt;td width=&quot;64%&quot;&gt;Confections&lt;/td&gt; &lt;/tr&gt; &lt;tr valign=&quot;top&quot;&gt; &lt;td width=&quot;36%&quot;&gt;&lt;b&gt;4&lt;/b&gt;&lt;/td&gt; &lt;td width=&quot;64%&quot;&gt;Dairy Products&lt;/td&gt; &lt;/tr&gt; &lt;tr valign=&quot;top&quot;&gt; &lt;td width=&quot;36%&quot;&gt;...&lt;/td&gt; &lt;td width=&quot;64%&quot;&gt;...&lt;/td&gt; &lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt; &lt;p&gt;Assume we already have created an ASP.NET Web page called ListProductsByCategory.aspx that accepts a Category ID value in the querystring and displays all of the products belonging to that category. So, users who wanted to view our Beverages for sale would visit ListProductsByCategory.aspx?CategoryID=1, while users who wanted to view our Dairy Products would visit ListProductsByCategory.aspx?CategoryID=4. Also assume we have a page called ListCategories.aspx, which lists the categories of products for sale.&lt;/p&gt; &lt;p&gt;Clearly this is a case for URL rewriting, as the URLs a user is presented with do not carry any significance for the user, nor do they provide any &quot;hackability.&quot; Rather, let&#39;s employ URL rewriting so that when a user visits /Products/Beverages.aspx, their URL will be rewritten to ListProductsByCategory.aspx?CategoryID=1. We can accomplish this with the following URL rewriting rule in the Web.config file:&lt;/p&gt; &lt;div class=&quot;code&quot; id=&quot;ctl00_rs1_mainContentContainer_ctl20_&quot;&gt;&lt;pre class=&quot;code&quot; id=&quot;ctl00_rs1_mainContentContainer_ctl20&quot; space=&quot;preserve&quot;&gt;&lt;rewriterconfig&gt;&lt;br /&gt;  &lt;rules&gt;&lt;br /&gt;     &lt;!-- Rules for Product Lister --&gt;&lt;br /&gt;     &lt;rewriterrule&gt;&lt;br /&gt;        &lt;lookfor&gt;~/Products/Beverages\.aspx&lt;/lookfor&gt;&lt;br /&gt;        &lt;sendto&gt;~/ListProductsByCategory.aspx?CategoryID=1&lt;/sendto&gt;&lt;br /&gt;     &lt;/rewriterrule&gt;&lt;br /&gt;     &lt;rewriterrule&gt;&lt;br /&gt;  &lt;/rules&gt;&lt;br /&gt;&lt;/rewriterconfig&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt; &lt;p&gt;As you can see, this rule searches to see if the path requested by the user was /Products/Beverages.aspx. If it was, it rewrites the URL as /ListProductsByCategory.aspx?CategoryID=1.&lt;/p&gt; &lt;blockquote class=&quot;dtBlock&quot;&gt; &lt;b class=&quot;le&quot;&gt;Note   &lt;/b&gt;Notice that the &lt;b&gt;&lt;lookfor&gt;&lt;/b&gt; element escapes the period in Beverages.aspx. This is because the &lt;b&gt;&lt;lookfor&gt;&lt;/b&gt; value is used in a regular expression pattern, and period is a special character in regular expressions meaning &quot;match any character,&quot; meaning a URL of /Products/BeveragesQaspx, for example, would match. By escaping the period (using \.) we are indicating that we want to match a literal period, and not any old character.&lt;/blockquote&gt; &lt;p&gt;With this rule in place, when a user visits /Products/Beverages.aspx, they will be shown the beverages for sale. Figure 3 shows a screenshot of a browser visiting /Products/Beverages.aspx. Notice that in the browser&#39;s Address bar the URL reads /Products/Beverages.aspx, but the user is actually seeing the contents of ListProductsByCategory.aspx?CategoryID=1. (In fact, there doesn&#39;t even exist a /Products/Beverages.aspx file on the Web server at all!)&lt;/p&gt; &lt;p class=&quot;fig&quot;&gt;&lt;img alt=&quot;&quot; src=&quot;http://msdn2.microsoft.com/en-us/library/ms972974.urlrewriting_fig03%28en-us,MSDN.10%29.gif&quot; border=&quot;0&quot; /&gt;&lt;/p&gt; &lt;p class=&quot;label&quot;&gt; &lt;/p&gt;&lt;p class=&quot;normal&quot;&gt; &lt;/p&gt;&lt;p class=&quot;label&quot;&gt;&lt;b&gt;Figure 3. Requesting category after rewriting URL&lt;/b&gt;&lt;/p&gt; &lt;p&gt;Similar to /Products/Beverages.aspx, we&#39;d next add rewriting rules for the other product categories. This simply involves adding additional &lt;b&gt;&lt;rewriterrule&gt;&lt;/b&gt; elements within the &lt;b&gt;&lt;rules&gt;&lt;/b&gt; element in the Web.config file. Consult the Web.config file in the download for the complete set of rewriting rules for the demo.&lt;/p&gt; &lt;p&gt;To make the URL more &quot;hackable,&quot; it would be nice if a user could simply hack off the Beverages.aspx from /Products/Beverages.aspx and be shown a listing of the product categories. At first glance, this may appear a trivial task—just add a rewriting rule that maps /Products/ to /ListCategories.aspx. However, there is a fine subtlety—you must first create a /Products/ directory and add an empty Default.aspx file in the /Products/ directory.&lt;/p&gt; &lt;p&gt;To understand why these extra steps need to be performed, recall that the URL rewriting engine is at the ASP.NET level. That is, if the ASP.NET engine is never given the opportunity to process the request, there&#39;s no way the URL rewriting engine can inspect the incoming URL. Furthermore, remember that IIS hands off incoming requests to the ASP.NET engine only if the requested file has an appropriate extension. So if a user visits /Products/, IIS doesn&#39;t see any file extension, so it checks the directory to see if there exists a file with one of the default filenames. (Default.aspx, Default.htm, Default.asp, and so on. These default filenames are defined in the Documents tab of the Web Server Properties dialog box in the IIS Administration dialog box.) Of course, if the /Products/ directory doesn&#39;t exist, IIS will return an HTTP 404 error. &lt;/p&gt; &lt;p&gt;So, we need to create the /Products/ directory. Additionally, we need to create a single file in this directory, Default.aspx. This way, when a user visits /Products/, IIS will inspect the directory, see that there exists a file named Default.aspx, and then hand off processing to the ASP.NET engine. Our URL rewriter, then, will get a crack at rewriting the URL.&lt;/p&gt; &lt;p&gt;After creating the directory and Default.aspx file, go ahead and add the following rewriting rule to the &lt;b&gt;&lt;rules&gt;&lt;/b&gt; element:&lt;/p&gt; &lt;div class=&quot;code&quot; id=&quot;ctl00_rs1_mainContentContainer_ctl21_&quot;&gt;&lt;pre class=&quot;code&quot; id=&quot;ctl00_rs1_mainContentContainer_ctl21&quot; space=&quot;preserve&quot;&gt;&lt;rewriterrule&gt;&lt;br /&gt;  &lt;lookfor&gt;~/Products/Default\.aspx&lt;/lookfor&gt;&lt;br /&gt;  &lt;sendto&gt;~/ListCategories.aspx&lt;/sendto&gt;&lt;br /&gt;&lt;/rewriterrule&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt; &lt;p&gt;With this rule in place, when a user visits /Products/ or /Products/Default.aspx, they will see the listing of product categories, shown in Figure 4.&lt;/p&gt; &lt;p class=&quot;fig&quot;&gt;&lt;img alt=&quot;&quot; src=&quot;http://msdn2.microsoft.com/en-us/library/ms972974.urlrewriting_fig04%28en-us,MSDN.10%29.gif&quot; border=&quot;0&quot; /&gt;&lt;/p&gt; &lt;p class=&quot;label&quot;&gt; &lt;/p&gt;&lt;p class=&quot;normal&quot;&gt; &lt;/p&gt;&lt;p class=&quot;label&quot;&gt;&lt;b&gt;Figure 4. Adding &quot;hackability&quot; to the URL&lt;/b&gt;&lt;/p&gt; &lt;h3 class=&quot;dtH1&quot;&gt;Handling Postbacks&lt;/h3&gt; &lt;p&gt;If the URLs you are rewriting contain a server-side Web Form and perform postbacks, when the form posts back, the underlying URL will be used. That is, if our user enters into their browser, /Products/Beverages.aspx, they will still see in their browser&#39;s Address bar, /Products/Beverages.aspx, but they will be shown the content for ListProductsByCategory.aspx?CategoryID=1. If ListProductsByCategory.aspx performs a postback, the user will be posted back to ListProductsByCategory.aspx?CategoryID=1, not /Products/Beverages.aspx. This won&#39;t break anything, but it can be disconcerting from the user&#39;s perspective to see the URL change suddenly upon clicking a button.&lt;/p&gt; &lt;p&gt;The reason this behavior happens is because when the Web Form is rendered, it explicitly sets its action attribute to the value of the file path in the &lt;b&gt;Request&lt;/b&gt; object. Of course, by the time the Web Form is rendered, the URL has been rewritten from /Products/Beverages.aspx to ListProductsByCategory.aspx?CategoryID=1, meaning the &lt;b&gt;Request&lt;/b&gt; object is reporting that the user is visiting ListProductsByCategory.aspx?CategoryID=1. This problem can be fixed by having the server-side form simply not render an action attribute. (Browsers, by default, will postback if the form doesn&#39;t contain an action attribute.)&lt;/p&gt; &lt;p&gt;Unfortunately, the Web Form does not allow you to explicitly specify an action attribute, nor does it allow you to set some property to disable the rendering of the action attribute. Rather, we&#39;ll have to extend the &lt;b&gt;System.Web.HtmlControls.HtmlForm&lt;/b&gt; class ourselves, overriding the &lt;b&gt;RenderAttribute()&lt;/b&gt; method and explicitly indicating that it not render the action attribute.&lt;/p&gt; &lt;p&gt;Thanks to the power of inheritance, we can gain all of the functionality of the &lt;b&gt;HtmlForm&lt;/b&gt; class and only have to add a scant few lines of code to achieve the desired behavior. The complete code for the custom class is shown below:&lt;/p&gt; &lt;div class=&quot;code&quot; id=&quot;ctl00_rs1_mainContentContainer_ctl22_&quot;&gt;&lt;pre class=&quot;code&quot; id=&quot;ctl00_rs1_mainContentContainer_ctl22&quot; space=&quot;preserve&quot;&gt;namespace ActionlessForm {&lt;br /&gt; public class Form : System.Web.UI.HtmlControls.HtmlForm&lt;br /&gt; {&lt;br /&gt;    protected override void RenderAttributes(HtmlTextWriter writer)&lt;br /&gt;    {&lt;br /&gt;       writer.WriteAttribute(&quot;name&quot;, this.Name);&lt;br /&gt;       base.Attributes.Remove(&quot;name&quot;);&lt;br /&gt;&lt;br /&gt;       writer.WriteAttribute(&quot;method&quot;, this.Method);&lt;br /&gt;       base.Attributes.Remove(&quot;method&quot;);&lt;br /&gt;&lt;br /&gt;       this.Attributes.Render(writer);&lt;br /&gt;&lt;br /&gt;       base.Attributes.Remove(&quot;action&quot;);&lt;br /&gt;&lt;br /&gt;       if (base.ID != null)&lt;br /&gt;          writer.WriteAttribute(&quot;id&quot;, base.ClientID);&lt;br /&gt;    }&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt; &lt;p&gt;The code for the overridden &lt;b&gt;RenderAttributes()&lt;/b&gt; method simply contains the exact code from the &lt;b&gt;HtmlForm&lt;/b&gt; class&#39;s &lt;b&gt;RenderAttributes()&lt;/b&gt; method, but without setting the action attribute. (I used Lutz Roeder&#39;s &lt;a onclick=&quot;javascript:Track(&#39;ctl00_rs1_mainContentContainer_ctl00|ctl00_rs1_mainContentContainer_ctl23&#39;,this);&quot; href=&quot;http://www.aisto.com/roeder/DotNet/&quot;&gt;Reflector&lt;/a&gt; to view the source code of the &lt;b&gt;HtmlForm&lt;/b&gt; class.)&lt;/p&gt; &lt;p&gt;Once you have created this class and compiled it, to use it in an ASP.NET Web application, start by adding it to the Web application&#39;s References folder. Then, to use it in place of the &lt;b&gt;HtmlForm&lt;/b&gt; class, simply add the following to the top of your ASP.NET Web page:&lt;/p&gt; &lt;div class=&quot;code&quot; id=&quot;ctl00_rs1_mainContentContainer_ctl24_&quot;&gt;&lt;pre class=&quot;code&quot; id=&quot;ctl00_rs1_mainContentContainer_ctl24&quot; space=&quot;preserve&quot;&gt;&lt;%@ Register TagPrefix=&quot;skm&quot; Namespace=&quot;ActionlessForm&quot;&lt;br /&gt;  Assembly=&quot;ActionlessForm&quot; %&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt; &lt;p&gt;Then, where you have &lt;code class=&quot;ce&quot;&gt;&lt;form runat=&quot;server&quot;&gt;&lt;/code&gt;, replace that with:&lt;/p&gt; &lt;div class=&quot;code&quot; id=&quot;ctl00_rs1_mainContentContainer_ctl25_&quot;&gt;&lt;pre class=&quot;code&quot; id=&quot;ctl00_rs1_mainContentContainer_ctl25&quot; space=&quot;preserve&quot;&gt;&lt;skm:form id=&quot;Form1&quot; method=&quot;post&quot; runat=&quot;server&quot;&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt; &lt;p&gt;and replace the closing &lt;code class=&quot;ce&quot;&gt;&lt;/form&gt;&lt;/code&gt; tag with:&lt;/p&gt; &lt;div class=&quot;code&quot; id=&quot;ctl00_rs1_mainContentContainer_ctl26_&quot;&gt;&lt;pre class=&quot;code&quot; id=&quot;ctl00_rs1_mainContentContainer_ctl26&quot; space=&quot;preserve&quot;&gt;&lt;/skm:Form&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt; &lt;p&gt;You can see this custom Web Form class in action in ListProductsByCategory.aspx, which is included in this article&#39;s download. Also included in the download is a Visual Studio .NET project for the action-less Web Form.&lt;/p&gt; &lt;blockquote class=&quot;dtBlock&quot;&gt; &lt;b class=&quot;le&quot;&gt;Note   &lt;/b&gt;If the URL you are rewriting to does not perform a postback, there&#39;s no need to use this custom Web Form class.&lt;/blockquote&gt; &lt;h2 class=&quot;dtH1&quot;&gt;&lt;a name=&quot;urlrewriting_topic7&quot;&gt;&lt;!----&gt;&lt;/a&gt;Creating Truly &quot;Hackable&quot; URLs&lt;/h2&gt; &lt;p&gt;The simple URL rewriting demonstrated in the previous section showed how easily the URL rewriting engine can be configured with new rewriting rules. The true power of the rewriting rules, though, shines when using regular expressions, as we&#39;ll see in this section.&lt;/p&gt; &lt;p&gt;Blogs are becoming more and more popular these days, and it seems &lt;i&gt;everyone&lt;/i&gt; has their own blog. If you are not familiar with blogs, they are often-updated personal pages that typically serve as an online journal. Most bloggers simply write about their day-to-day happenings, others focus on blogging about a specific theme, such as movie reviews, a sports team, or a computer technology.&lt;/p&gt; &lt;p&gt;Depending on the author, blogs are updated anywhere from several times a day to once every week or two. Typically the blog homepage shows the most recent 10 entries, but virtually all blogging software provides an archive through which visitors can read older postings. Blogs are a great application for &quot;hackable&quot; URLs. Imagine while searching through the archives of a blog you found yourself at the URL /2004/02/14.aspx. Would you be terribly surprised if you found yourself reading the posts made on February 14th, 2004? Furthermore, you might want to view all posts for February 2004, in which case you might try hacking the URL to /2004/02/. To view all 2004 posts, you might try visiting /2004/.&lt;/p&gt; &lt;p&gt;When maintaining a blog, it would be nice to provide this level of URL &quot;hackability&quot; to your visitors. While many blog engines provide this functionality, let&#39;s look at how it can be accomplished using URL rewriting. &lt;/p&gt; &lt;p&gt;First, we need a single ASP.NET Web page that will show blog entries by day, month, or year. Assume we have such a page, ShowBlogContent.aspx, that takes in querystring parameters year, month, and day. To view the posts for February 14th, 2004, we could visit ShowBlogContent.aspx?year=2004&amp;amp;month=2&amp;amp;day=14. To view all posts for February 2004, we&#39;d visit ShowBlogContent.aspx?year=2004&amp;amp;month=2. Finally, to see all posts for the year 2004, we&#39;d navigate to ShowBlogContent.aspx?year=2004. (The code for ShowBlogContent.aspx can be found in this article&#39;s download.)&lt;/p&gt; &lt;p&gt;So, if a user visits /2004/02/14.aspx, we need to rewrite the URL to ShowBlogContent.aspx?year=2004&amp;amp;month=2&amp;amp;day=14. All three cases—when the URL specifies a year, month, and day; when the URL specifies just the year and month; and when the URL specifies only the yea—can be handled with three rewrite rules:&lt;/p&gt; &lt;div class=&quot;code&quot; id=&quot;ctl00_rs1_mainContentContainer_ctl27_&quot;&gt;&lt;pre class=&quot;code&quot; id=&quot;ctl00_rs1_mainContentContainer_ctl27&quot; space=&quot;preserve&quot;&gt;&lt;rewriterconfig&gt;&lt;br /&gt;  &lt;rules&gt;&lt;br /&gt;     &lt;!-- Rules for Blog Content Displayer --&gt;&lt;br /&gt;     &lt;rewriterrule&gt;&lt;br /&gt;        &lt;lookfor&gt;~/(\d{4})/(\d{2})/(\d{2})\.aspx&lt;/lookfor&gt;&lt;br /&gt;        &lt;sendto&gt;~/ShowBlogContent.aspx?year=$1&amp;amp;month=$2&amp;amp;day=$3&lt;/sendto&gt;&lt;br /&gt;     &lt;/rewriterrule&gt;&lt;br /&gt;     &lt;rewriterrule&gt;&lt;br /&gt;        &lt;lookfor&gt;~/(\d{4})/(\d{2})/Default\.aspx&lt;/lookfor&gt;&lt;br /&gt;        &lt;sendto&gt;&lt;![CDATA[~/ShowBlogContent.aspx?year=$1&amp;amp;month=$2]]&gt;&lt;/sendto&gt;&lt;br /&gt;     &lt;/rewriterrule&gt;&lt;br /&gt;     &lt;rewriterrule&gt;&lt;br /&gt;        &lt;lookfor&gt;~/(\d{4})/Default\.aspx&lt;/lookfor&gt;&lt;br /&gt;        &lt;sendto&gt;~/ShowBlogContent.aspx?year=$1&lt;/sendto&gt;&lt;br /&gt;     &lt;/rewriterrule&gt;&lt;br /&gt;  &lt;/rules&gt;&lt;br /&gt;&lt;/rewriterconfig&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt; &lt;p&gt;These rewriting rules demonstrate the power of regular expressions. In the first rule, we look for a URL with the pattern (\d{4})/(\d{2})/(\d{2})\.aspx. In plain English, this matches a string that has four digits followed by a forward slash followed by two digits followed by a forward slash, followed by two digits followed by .aspx. The parenthesis around each digit grouping is vital—it allows us to refer to the matched characters inside those parentheses in the corresponding &lt;b&gt;&lt;sendto&gt;&lt;/b&gt; property. Specifically, we can refer back to the matched parenthetical groupings using $1, $2, and $3 for the first, second, and third parenthesis grouping, respectively.&lt;/p&gt; &lt;blockquote class=&quot;dtBlock&quot;&gt; &lt;b class=&quot;le&quot;&gt;Note   &lt;/b&gt;Since the Web.config file is XML-formatted, characters like &amp;amp;, &lt;, and &gt; in the text portion of an element must be escaped. In the first rule&#39;s &lt;b&gt;&lt;sendto&gt;&lt;/b&gt; element, &amp;amp; is escaped to &amp;amp;. In the second rule&#39;s &lt;b&gt;&lt;sendto&gt;&lt;/b&gt;, an alternative technique is used—by using a &lt;b&gt;&lt;![CDATA[...]]&gt;&lt;/b&gt; element, the contents inside do not need to be escaped. Either approach is acceptable and accomplishes the same end.&lt;/blockquote&gt; &lt;p&gt;Figures 5, 6, and 7 show the URL rewriting in action. The data is actually being pulled from my blog, &lt;a onclick=&quot;javascript:Track(&#39;ctl00_rs1_mainContentContainer_ctl00|ctl00_rs1_mainContentContainer_ctl28&#39;,this);&quot; href=&quot;http://scottonwriting.net/&quot;&gt;http://ScottOnWriting.NET&lt;/a&gt;. In Figure 5, the posts for November 7, 2003 are shown; in Figure 6 all posts for November 2003 are shown; Figure 7 shows all posts for 2003.&lt;/p&gt; &lt;p class=&quot;fig&quot;&gt;&lt;img alt=&quot;&quot; src=&quot;http://msdn2.microsoft.com/en-us/library/ms972974.urlrewriting_fig05%28en-us,MSDN.10%29.gif&quot; border=&quot;0&quot; /&gt;&lt;/p&gt; &lt;p class=&quot;label&quot;&gt; &lt;/p&gt;&lt;p class=&quot;normal&quot;&gt; &lt;/p&gt;&lt;p class=&quot;label&quot;&gt;&lt;b&gt;Figure 5. Posts for November 7, 2003&lt;/b&gt;&lt;/p&gt; &lt;p class=&quot;fig&quot;&gt;&lt;img alt=&quot;&quot; src=&quot;http://msdn2.microsoft.com/en-us/library/ms972974.urlrewriting_fig06%28en-us,MSDN.10%29.gif&quot; border=&quot;0&quot; /&gt;&lt;/p&gt; &lt;p class=&quot;label&quot;&gt; &lt;/p&gt;&lt;p class=&quot;normal&quot;&gt; &lt;/p&gt;&lt;p class=&quot;label&quot;&gt;&lt;b&gt;Figure 6. All posts for November 2003&lt;/b&gt;&lt;/p&gt; &lt;p class=&quot;fig&quot;&gt;&lt;img alt=&quot;&quot; src=&quot;http://msdn2.microsoft.com/en-us/library/ms972974.urlrewriting_fig07%28en-us,MSDN.10%29.gif&quot; border=&quot;0&quot; /&gt;&lt;/p&gt; &lt;p class=&quot;label&quot;&gt; &lt;/p&gt;&lt;p class=&quot;normal&quot;&gt; &lt;/p&gt;&lt;p class=&quot;label&quot;&gt;&lt;b&gt;Figure 7. All posts for 2003&lt;/b&gt;&lt;/p&gt; &lt;blockquote class=&quot;dtBlock&quot;&gt; &lt;b class=&quot;le&quot;&gt;Note   &lt;/b&gt;The URL rewriting engine expects a regular expression pattern in the &lt;b&gt;&lt;lookfor&gt;&lt;/b&gt; elements. If you are unfamiliar with regular expressions, consider reading an earlier article of mine, &lt;a onclick=&quot;javascript:Track(&#39;ctl00_rs1_mainContentContainer_ctl00|ctl00_rs1_mainContentContainer_ctl29&#39;,this);&quot; href=&quot;http://www.4guysfromrolla.com/webtech/090199-1.shtml&quot;&gt;An Introduction to Regular Expressions&lt;/a&gt;. Also, a great place to get your hands on commonly used regular expressions, as well as a repository for sharing your own crafted regular expressions, is &lt;a onclick=&quot;javascript:Track(&#39;ctl00_rs1_mainContentContainer_ctl00|ctl00_rs1_mainContentContainer_ctl30&#39;,this);&quot; href=&quot;http://regexlib.com/&quot;&gt;RegExLib.com&lt;/a&gt;.&lt;/blockquote&gt; &lt;h3 class=&quot;dtH1&quot;&gt;Building the Requisite Directory Structure&lt;/h3&gt; &lt;p&gt;When a request comes in for /2004/03/19.aspx, IIS notes the .aspx extension and routes the request to the ASP.NET engine. As the request moves through the ASP.NET engine&#39;s pipeline, the URL will get rewritten to ShowBlogContent.aspx?year=2004&amp;amp;month=03&amp;amp;day=19 and the visitor will see those blog entries for March 19, 2004. But what happens when the user navigates to /2004/03/? Unless there is a directory /2004/03/, IIS will return a 404 error. Furthermore, there needs to be a Default.aspx page in this directory so that the request is handed off to the ASP.NET engine.&lt;/p&gt; &lt;p&gt;So with this approach, you have to manually create a directory for each year in which there are blog entries, with a Default.aspx page in the directory. Additionally, in each year directory you need to manually create twelve more directories—01, 02, …, 12—each with a Default.aspx file. (Recall that we had to do the same thing—add a /Products/ directory with a Default.aspx file—in the previous demo so that visiting /Products/ correctly displayed ListCategories.aspx.)&lt;/p&gt; &lt;p&gt;Clearly, adding such a directory structure can be a pain. A workaround to this problem is to have all incoming IIS requests map to the ASP.NET engine. This way, even if when visiting the URL /2004/03/, IIS will faithfully hand off the request to the ASP.NET engine even if there does not exist a /2004/03/ directory. Using this approach, however, makes the ASP.NET engine responsible for handling all types of incoming requests to the Web server, including images, CSS files, external JavaScript files, Macromedia Flash files, and so on.&lt;/p&gt; &lt;p&gt;A thorough discussion of handling all file types is far beyond the scope of this article. For an example of an ASP.NET Web application that uses this technique, though, look into &lt;a onclick=&quot;javascript:Track(&#39;ctl00_rs1_mainContentContainer_ctl00|ctl00_rs1_mainContentContainer_ctl31&#39;,this);&quot; href=&quot;http://www.gotdotnet.com/community/workspaces/default.aspx&quot;&gt;.Text&lt;/a&gt;, an open-source blog engine. .Text can be configured to have all requests mapped to the ASP.NET engine. It can handle serving all file types by using a custom HTTP handler that knows how to serve up typical static file types (images, CSS files, and so on).&lt;/p&gt; &lt;h2 class=&quot;dtH1&quot;&gt;&lt;a name=&quot;urlrewriting_topic8&quot;&gt;&lt;!----&gt;&lt;/a&gt;Conclusion&lt;/h2&gt; &lt;p&gt;In this article we examined how to perform URL rewriting at the ASP.NET-level through the &lt;b&gt;HttpContext&lt;/b&gt; class&#39;s &lt;b&gt;RewriteUrl()&lt;/b&gt; method. As we saw, &lt;b&gt;RewriteUrl()&lt;/b&gt; updates the particular &lt;b&gt;HttpContext&#39;s&lt;/b&gt; &lt;b&gt;Request&lt;/b&gt; property, updating what file and path is being requested. The net effect is that, from the user&#39;s perspective, they are visiting a particular URL, but actually a different URL is being requested on the Web server side.&lt;/p&gt; &lt;p&gt;URLs can be rewritten either in an HTTP module or an HTTP handler. In this article we examined using an HTTP module to perform the rewriting, and looked at the consequences of performing the rewriting at different stages in the pipeline.&lt;/p&gt; &lt;p&gt;Of course, with ASP.NET-level rewriting, the URL rewriting can only happen if the request is successfully handed off from IIS to the ASP.NET engine. This naturally occurs when the user requests a page with a .aspx extension. However, if you want the person to be able to enter a URL that might not actually exist, but would rather rewrite to an existing ASP.NET page, you have to either create mock directories and Default.aspx pages, or configure IIS so that all incoming requests are blindly routed to the ASP.NET engine.&lt;/p&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;octopus east java baker&lt;/div&gt;</description><link>http://scriptster.blogspot.com/2007/12/url-rewriting-in-aspnet.html</link><author>noreply@blogger.com (Octopus)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-2977499297091575918.post-4775566815380140130</guid><pubDate>Mon, 17 Dec 2007 03:50:00 +0000</pubDate><atom:updated>2007-12-16T19:51:45.152-08:00</atom:updated><title>Redirect, Transfer or Rewrite?</title><description>&lt;p&gt;Earlier, we implemented a URL rewriting scheme; however, in some circumstances,   you may wish to implement a &lt;code&gt;Response.Redirect()&lt;/code&gt; or &lt;code&gt;Server.Transfer()&lt;/code&gt;  instead. One reason to do this is to forward from Default.aspx to another page,   like Home.aspx. You may or may not want to do this &quot;behind the scenes,&quot; but   that is a decision for you to make yourself. As always, each option comes with   its own set of pros and cons. &lt;/p&gt; &lt;p&gt;Redirects are essentially two GET (or POST) requests. The first request gets   processed and then the &lt;code&gt;Response.Redirect()&lt;/code&gt; sends a response back   to the client with an HTTP 302 redirect command. This obviously causes a slight   delay as the second request gets processed. Also, since the new URL is sent to   the client, it won&#39;t be hidden. This clearly doesn&#39;t support URL   beautification, which is the main reason most people implement handlers. Even   though redirects won&#39;t solve your problems, they still play an important part   in the overall solution and should be considered when developing your mapping   solution. &lt;/p&gt; &lt;p&gt;Transfers, unlike redirects, keep control within the application; but, they are   still &lt;u&gt;treated as two requests&lt;/u&gt;. The difference is that instead of the   client handling the HTTP 302 redirect command, the web server handles it. This   means that any modules, as well as the handler, will be &lt;u&gt;processed twice&lt;/u&gt; .   There are three key things to remember when using transfers: (&lt;strong&gt;1&lt;/strong&gt;)   the &lt;code&gt;Request&lt;/code&gt; object, and all of its properties and methods, will   reflect the initial request (logical page) and &lt;em&gt;not&lt;/em&gt; the physical page;   (&lt;strong&gt;2&lt;/strong&gt;) post-back will not work; and, (&lt;strong&gt;3&lt;/strong&gt;) in   order to use the transfer you have to have two handlers specified in the   Web.config file. There might be a way to get the post-back to work, but I don&#39;t   know what that would entail. Perhaps I will delve into the ASP.NET request   process fully one day. As for the two handler issue, let me explain that in a   bit more detail. As you may remember from above, you specified two handlers in   the Web.config file. The reason for this is because after the &lt;code&gt;Server.Transfer()&lt;/code&gt;   is executed, ASP.NET will send the second request back through the handler. I&#39;m   not completely sure why this is a problem, but it is. So, to fix it, you need   to have some way to identify what requests should be handled by ASP.NET&#39;s   default handler and which should be handled by yours. I attacked this by   putting all of my physical pages in a Pages directory. So, by re-adding the   default handler to handle all requests to &lt;code&gt;&quot;*/Pages/*.aspx&quot;&lt;/code&gt;, we   tell ASP.NET how to support each type of request. As I also mentioned before,   this will fix the the &quot;&lt;span style=&quot;color:red;&quot;&gt;Error executing child request&lt;/span&gt;&quot;   error.&lt;/p&gt; &lt;p&gt;Rewrites provide the best performance because there is no back-tracking to   re-handle requests. You simply change the URL and continue on with the request   processing. Know that accessing the &lt;code&gt;Request&lt;/code&gt; object will now   reflect the new (physical) URL and you will not have access to the old   (logical) URL. You can get around this by adding custom variables to the &lt;code&gt;HttpContext&lt;/code&gt;,   but that shouldn&#39;t be necessary for most situations. &lt;/p&gt; &lt;p&gt;To add support for redirects and transfers, we can simply change our Web.config   file by prepending &quot;redirect.&quot;, &quot;transfer.&quot;, or &quot;rewrite.&quot; to identify how we   want the request handled. Then, update the &lt;code&gt;IHttpHandler.ProcessRequest()&lt;/code&gt;   method to treat them accordingly.&lt;/p&gt; &lt;div class=&quot;code&quot;&gt;   &lt;h3&gt;HttpHandler.ProcessRequest() Method&lt;/h3&gt;   &lt;code&gt;     &lt;span style=&quot;color:blue;&quot;&gt;public void&lt;/span&gt; ProcessRequest(HttpContext context)&lt;br /&gt;  {&lt;br /&gt;&lt;span style=&quot;color:green;&quot;&gt;  // declare vars&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color:blue;&quot;&gt;  string&lt;/span&gt; requestedUrl;&lt;br /&gt;&lt;span style=&quot;color:blue;&quot;&gt;  string&lt;/span&gt; targetUrl;&lt;br /&gt;&lt;span style=&quot;color:blue;&quot;&gt;  int&lt;/span&gt; urlLength;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color:green;&quot;&gt;  // save requested, target url&lt;/span&gt;&lt;br /&gt;    requestedUrl = context.Request.RawUrl;&lt;br /&gt;&lt;span style=&quot;color:blue;&quot;&gt;  if&lt;/span&gt; ( requestedUrl.IndexOf(&quot;?&quot;) &gt;= 0 )&lt;br /&gt;      targetUrl =    ConfigurationSettings.AppSettings[requestedUrl.Substring(0,    requestedUrl.IndexOf(&quot;?&quot;))];&lt;br /&gt;&lt;span style=&quot;color:blue;&quot;&gt;  else&lt;/span&gt;&lt;br /&gt;      targetUrl = ConfigurationSettings.AppSettings[requestedUrl];   &lt;br /&gt;&lt;span style=&quot;color:blue;&quot;&gt;  if&lt;/span&gt; ( targetUrl == &lt;span style=&quot;color:blue;&quot;&gt;null&lt;/span&gt;   || targetUrl.Length == 0 )&lt;br /&gt;      targetUrl = requestedUrl;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color:green;&quot;&gt;  // handle type&lt;/span&gt;     &lt;br /&gt;&lt;span style=&quot;color:blue;&quot;&gt;  if&lt;/span&gt; ( targetUrl.StartsWith(&quot;redirect.&quot;) )&lt;br /&gt;    {&lt;br /&gt;      context.Response.Redirect(targetUrl.Substring(9));&lt;br /&gt;    }&lt;br /&gt;&lt;span style=&quot;color:blue;&quot;&gt;  else if&lt;/span&gt; ( targetUrl.StartsWith(&quot;transfer.&quot;) )&lt;br /&gt;    {&lt;br /&gt;      context.Server.Transfer(targetUrl.Substring(9));&lt;br /&gt;    }&lt;br /&gt;&lt;span style=&quot;color:blue;&quot;&gt;  else&lt;/span&gt;&lt;br /&gt;    {&lt;br /&gt;&lt;span style=&quot;color:green;&quot;&gt;    // if type is specified, remove it&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color:blue;&quot;&gt;    if&lt;/span&gt; (    targetUrl.StartsWith(&quot;rewrite.&quot;) )&lt;br /&gt;         targetUrl = targetUrl.Substring(8);&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color:green;&quot;&gt;    // save target url length&lt;/span&gt;&lt;br /&gt;      urlLength = targetUrl.IndexOf(&quot;?&quot;);&lt;br /&gt;&lt;span style=&quot;color:blue;&quot;&gt;    if&lt;/span&gt; ( urlLength == -1 )&lt;br /&gt;         urlLength = targetUrl.Length;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color:green;&quot;&gt;    // rewrite path&lt;/span&gt;&lt;br /&gt;      context.RewritePath(targetUrl);&lt;br /&gt;      IHttpHandler handler = PageParser.GetCompiledPageInstance(&lt;br /&gt;       targetUrl.Substring(0, urlLength), &lt;span style=&quot;color:blue;&quot;&gt;null&lt;/span&gt;,    context );&lt;br /&gt;      handler.ProcessRequest(context);&lt;br /&gt;    }&lt;br /&gt;  }&lt;/code&gt; &lt;/div&gt; &lt;p&gt;   &lt;b&gt;Conclusion&lt;/b&gt; &lt;/p&gt; &lt;p&gt;Well, congratulations on your first HTTP handler implementation. There is plenty   of room for improvement, so try to think of how you can manage the mappings to   add more than just a simple URL rewriting scheme. One thing that you might want   to consider is a post-back processing component. Yes, post-back is handled by   ASP.NET, but performance can be increased by removing that overhead. Anyway, my   point is that there are a lot of things you can do to improve this simple   implementation. I encourage you to add to this and let me know how well it   works out for you. I&#39;d be interested to hear some of the things people are   doing with handlers. Good luck! &lt;/p&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;octopus east java baker&lt;/div&gt;</description><link>http://scriptster.blogspot.com/2007/12/redirect-transfer-or-rewrite.html</link><author>noreply@blogger.com (Octopus)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-2977499297091575918.post-6501812312296256707</guid><pubDate>Fri, 14 Dec 2007 14:37:00 +0000</pubDate><atom:updated>2007-12-14T06:41:49.462-08:00</atom:updated><title>Json.NET 1.1: Converting between XML and JSON</title><description>JAVASCRIPT:&lt;br /&gt;&lt;br /&gt;  1.&lt;br /&gt;     &lt;br /&gt;  2.&lt;br /&gt;     XmlDocument doc = new XmlDocument();&lt;br /&gt;  3.&lt;br /&gt;     doc.LoadXml(@&quot;&lt;br /&gt;  4.&lt;br /&gt;     &lt;root&gt;&lt;br /&gt;  5.&lt;br /&gt;       &lt;person id=&quot;&quot; 1=&quot;&quot;&gt;&lt;br /&gt;  6.&lt;br /&gt;         &lt;name&gt;Alan&lt;/name&gt;&lt;br /&gt;  7.&lt;br /&gt;         &lt;url&gt;http://www.google.com&lt;/url&gt;&lt;br /&gt;  8.&lt;br /&gt;       &lt;/person&gt;&lt;br /&gt;  9.&lt;br /&gt;       &lt;person id=&quot;&quot; 2=&quot;&quot;&gt;&lt;br /&gt; 10.&lt;br /&gt;         &lt;name&gt;Louis&lt;/name&gt;&lt;br /&gt; 11.&lt;br /&gt;         &lt;url&gt;http://www.yahoo.com&lt;/url&gt;&lt;br /&gt; 12.&lt;br /&gt;       &lt;/person&gt;&lt;br /&gt; 13.&lt;br /&gt;     &lt;/root&gt;&quot;);&lt;br /&gt; 14.&lt;br /&gt;     &lt;br /&gt; 15.&lt;br /&gt;     string jsonText = JavaScriptConvert.SerializeXmlNode(doc);&lt;br /&gt; 16.&lt;br /&gt;     //{&lt;br /&gt; 17.&lt;br /&gt;     //  &quot;?xml&quot;: {&lt;br /&gt; 18.&lt;br /&gt;     //    &quot;@version&quot;: &quot;1.0&quot;,&lt;br /&gt; 19.&lt;br /&gt;     //    &quot;@standalone&quot;: &quot;no&quot;&lt;br /&gt; 20.&lt;br /&gt;     //  },&lt;br /&gt; 21.&lt;br /&gt;     //  &quot;root&quot;: {&lt;br /&gt; 22.&lt;br /&gt;     //    &quot;person&quot;: [&lt;br /&gt; 23.&lt;br /&gt;     //      {&lt;br /&gt; 24.&lt;br /&gt;     //        &quot;@id&quot;: &quot;1&quot;,&lt;br /&gt; 25.&lt;br /&gt;     //        &quot;name&quot;: &quot;Alan&quot;,&lt;br /&gt; 26.&lt;br /&gt;     //        &quot;url&quot;: &quot;http://www.google.com&quot;&lt;br /&gt; 27.&lt;br /&gt;     //      },&lt;br /&gt; 28.&lt;br /&gt;     //      {&lt;br /&gt; 29.&lt;br /&gt;     //        &quot;@id&quot;: &quot;2&quot;,&lt;br /&gt; 30.&lt;br /&gt;     //        &quot;name&quot;: &quot;Louis&quot;,&lt;br /&gt; 31.&lt;br /&gt;     //        &quot;url&quot;: &quot;http://www.yahoo.com&quot;&lt;br /&gt; 32.&lt;br /&gt;     //      }&lt;br /&gt; 33.&lt;br /&gt;     //    ]&lt;br /&gt; 34.&lt;br /&gt;     //  }&lt;br /&gt; 35.&lt;br /&gt;     //}&lt;br /&gt; 36.&lt;br /&gt;     &lt;br /&gt; 37.&lt;br /&gt;     XmlDocument newDoc = (XmlDocument)JavaScriptConvert.DeerializeXmlNode(jsonText);&lt;br /&gt; 38.&lt;br /&gt;     &lt;br /&gt; 39.&lt;br /&gt;     Assert.AreEqual(doc.InnerXml, newDoc.InnerXml);&lt;br /&gt; 40.&lt;div class=&quot;blogger-post-footer&quot;&gt;octopus east java baker&lt;/div&gt;</description><link>http://scriptster.blogspot.com/2007/12/jsonnet-11-converting-between-xml-and.html</link><author>noreply@blogger.com (Octopus)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-2977499297091575918.post-6159401087762394457</guid><pubDate>Fri, 14 Dec 2007 14:22:00 +0000</pubDate><atom:updated>2007-12-14T06:23:38.528-08:00</atom:updated><title>Json.NET - Simplifying .NET &lt;-&gt; JavaScript communication</title><description>&lt;div class=&quot;BlogPostArea&quot;&gt;&lt;p style=&quot;color: rgb(102, 102, 102); padding-top: 0pt; margin-top: 0pt; font-size: 1em;&quot;&gt;&lt;span&gt;&lt;input name=&quot;ctl00$Main$InlineTagEditorPanel$ctl01&quot; id=&quot;ctl00_Main_InlineTagEditorPanel_ctl01_State&quot; value=&quot;value:Filed%20under%3A%20%3Ca%20href%3D%22%2Farchive%2Ftags%2F.NET%2Fdefault.aspx%22%20rel%3D%22tag%22%3E.NET%3C%2Fa%3E&quot; type=&quot;hidden&quot;&gt;&lt;/span&gt;                                                                                                 &lt;/p&gt;&lt;span id=&quot;ctl00_Main_InlineTagEditorPanel_ctl01&quot;&gt;&lt;/span&gt; &lt;a href=&quot;http://www.json.org/&quot; target=&quot;_blank&quot;&gt;JSON&lt;/a&gt; (JavaScript Object Notation) is lightweight data interchange format. In recent times JSON has achieved widespread use due to the ease of which it can be parsed and then the data accessed from within JavaScript compared to &lt;a href=&quot;http://www.json.org/xml.html&quot; target=&quot;_blank&quot;&gt;alternatives like XML&lt;/a&gt;.&lt;div class=&quot;BlogPostContent bodytext&quot;&gt; &lt;p&gt;While many JavaScript libraries exist for converting JSON text to and from a JavaScript object, working with JSON in .NET has been much more problematic. Correctly escaping strings and building up objects when writing JSON text can be difficult and error prone, while parsing values back out of JSON text is harder still.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Json.NET&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;Json.NET is a JSON .NET API for simply and safely reading and writing valid JSON text. At the core of Json.NET, similar to the .NET XML APIs, are two classes: JsonReader and JsonWriter. Also like XML in .NET, Json.NET includes a JsonSerializer class.&lt;/p&gt; &lt;h4&gt;Reading JSON&lt;/h4&gt; &lt;p&gt;JsonReader is a fast, forward only, readonly cursor. Like XmlTextReader it works over the top of a TextReader and maximizes performance while minimizing memory use.&lt;/p&gt; &lt;p&gt;The following code is a brief example of how to read a JSON object.&lt;/p&gt; &lt;div class=&quot;overflowpanel&quot;&gt; &lt;div class=&quot;code&quot; style=&quot;background: white none repeat scroll 0% 50%; font-size: 9pt; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; color: black; font-family: Courier New;&quot;&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color: blue;&quot;&gt;string&lt;/span&gt; jsonText = &lt;span style=&quot;color: maroon;&quot;&gt;&quot;[&#39;JSON!&#39;,1,true,{property:&#39;value&#39;}]&quot;&lt;/span&gt;;&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt; &lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color: teal;&quot;&gt;JsonReader&lt;/span&gt; reader = &lt;span style=&quot;color: blue;&quot;&gt;new&lt;/span&gt; &lt;span style=&quot;color: teal;&quot;&gt;JsonReader&lt;/span&gt;(&lt;span style=&quot;color: blue;&quot;&gt;new&lt;/span&gt; &lt;span style=&quot;color: teal;&quot;&gt;StringReader&lt;/span&gt;(jsonText));&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt; &lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color: teal;&quot;&gt;Console&lt;/span&gt;.WriteLine(&lt;span style=&quot;color: maroon;&quot;&gt;&quot;TokenType\t\tValueType\t\tValue&quot;&lt;/span&gt;);&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt; &lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color: blue;&quot;&gt;while&lt;/span&gt; (reader.Read())&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;{&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;    &lt;span style=&quot;color: teal;&quot;&gt;Console&lt;/span&gt;.WriteLine(reader.TokenType + &lt;span style=&quot;color: maroon;&quot;&gt;&quot;\t\t&quot;&lt;/span&gt; + WriteValue(reader.ValueType) + &lt;span style=&quot;color: maroon;&quot;&gt;&quot;\t\t&quot;&lt;/span&gt; + WriteValue(reader.Value))&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;}&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt; &lt;p&gt;Resulting in...&lt;/p&gt; &lt;table class=&quot;grid&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot;&gt;  &lt;tbody&gt;&lt;tr&gt; &lt;th&gt;TokenType&lt;/th&gt; &lt;th&gt;ValueType&lt;/th&gt; &lt;th&gt;Value&lt;/th&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td&gt;StartArray &lt;/td&gt; &lt;td&gt;null &lt;/td&gt; &lt;td&gt;null &lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td&gt;String &lt;/td&gt; &lt;td&gt;System.String &lt;/td&gt; &lt;td&gt;JSON! &lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td&gt;Integer &lt;/td&gt; &lt;td&gt;System.Int32 &lt;/td&gt; &lt;td&gt;1 &lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td&gt;Boolean &lt;/td&gt; &lt;td&gt;System.Boolean &lt;/td&gt; &lt;td&gt;True &lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td&gt;StartObject &lt;/td&gt; &lt;td&gt;null &lt;/td&gt; &lt;td&gt;null &lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td&gt;PropertyName &lt;/td&gt; &lt;td&gt;System.String &lt;/td&gt; &lt;td&gt;property &lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td&gt;String &lt;/td&gt; &lt;td&gt;System.String &lt;/td&gt; &lt;td&gt;value &lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td&gt;EndObject &lt;/td&gt; &lt;td&gt;null &lt;/td&gt; &lt;td&gt;null &lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td&gt;EndArray &lt;/td&gt; &lt;td&gt;null &lt;/td&gt; &lt;td&gt;null &lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt; &lt;h4&gt;Writing JSON&lt;/h4&gt; &lt;p&gt;JsonWriter is also forward only, and writes JSON text to a TextWriter. It handles formatting numbers, escaping strings and validating that the object is valid.&lt;/p&gt; &lt;p&gt;The following code is a brief example of how to write a JSON object.&lt;/p&gt; &lt;div class=&quot;overflowpanel&quot;&gt; &lt;div class=&quot;code&quot; style=&quot;background: white none repeat scroll 0% 50%; font-size: 9pt; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; color: black; font-family: Courier New;&quot;&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color: teal;&quot;&gt;StringWriter&lt;/span&gt; sw = &lt;span style=&quot;color: blue;&quot;&gt;new&lt;/span&gt; &lt;span style=&quot;color: teal;&quot;&gt;StringWriter&lt;/span&gt;();&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color: teal;&quot;&gt;JsonWriter&lt;/span&gt; writer = &lt;span style=&quot;color: blue;&quot;&gt;new&lt;/span&gt; &lt;span style=&quot;color: teal;&quot;&gt;JsonWriter&lt;/span&gt;(sw);&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt; &lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;writer.WriteStartArray();&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;writer.WriteValue(&lt;span style=&quot;color: maroon;&quot;&gt;&quot;JSON!&quot;&lt;/span&gt;);&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;writer.WriteValue(1);&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;writer.WriteValue(&lt;span style=&quot;color: blue;&quot;&gt;true&lt;/span&gt;);&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;writer.WriteStartObject();&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;writer.WritePropertyName(&lt;span style=&quot;color: maroon;&quot;&gt;&quot;property&quot;&lt;/span&gt;);&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;writer.WriteValue(&lt;span style=&quot;color: maroon;&quot;&gt;&quot;value&quot;&lt;/span&gt;);&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;writer.WriteEndObject();&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;writer.WriteEndArray();&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt; &lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;writer.Flush();&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt; &lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color: blue;&quot;&gt;string&lt;/span&gt; jsonText = sw.GetStringBuilder().ToString();&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt; &lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color: teal;&quot;&gt;Console&lt;/span&gt;.WriteLine(jsonText);&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color: green;&quot;&gt;// [&#39;JSON!&#39;,1,true,{property:&#39;value&#39;}]&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt; &lt;p&gt;Which prints out: &lt;code&gt;[&#39;JSON!&#39;,1,true,{property:&#39;value&#39;}]&lt;/code&gt;.&lt;/p&gt; &lt;h4&gt;Serializing and deserializing JSON and .NET objects&lt;/h4&gt; &lt;p&gt;JsonSerializer, similar to XML serialization, provides a hassle free way to automatically convert .NET objects to and from JSON text.&lt;/p&gt; &lt;p&gt;The following code is a brief example of how to serialize and deserialize JSON and .NET objects.&lt;/p&gt; &lt;div class=&quot;overflowpanel&quot;&gt; &lt;div class=&quot;code&quot; style=&quot;background: white none repeat scroll 0% 50%; font-size: 9pt; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; color: black; font-family: Courier New;&quot;&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color: blue;&quot;&gt;string&lt;/span&gt; jsonText = &lt;span style=&quot;color: maroon;&quot;&gt;&quot;[&#39;JSON!&#39;,1,true,{property:&#39;value&#39;}]&quot;&lt;/span&gt;;&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt; &lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color: teal;&quot;&gt;JsonSerializer&lt;/span&gt; serializer = &lt;span style=&quot;color: blue;&quot;&gt;new&lt;/span&gt; &lt;span style=&quot;color: teal;&quot;&gt;JsonSerializer&lt;/span&gt;();&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt; &lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color: teal;&quot;&gt;JavaScriptArray&lt;/span&gt; jsArray = (&lt;span style=&quot;color: teal;&quot;&gt;JavaScriptArray&lt;/span&gt;) serializer.Deserialize(&lt;span style=&quot;color: blue;&quot;&gt;new&lt;/span&gt; &lt;span style=&quot;color: teal;&quot;&gt;JsonReader&lt;/span&gt;(&lt;span style=&quot;color: blue;&quot;&gt;new&lt;/span&gt; &lt;span style=&quot;color: teal;&quot;&gt;StringReader&lt;/span&gt;(jsonText)));&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt; &lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color: teal;&quot;&gt;Console&lt;/span&gt;.WriteLine(jsArray[0]);&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color: green;&quot;&gt;// JSON!&lt;/span&gt;&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt; &lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color: teal;&quot;&gt;JavaScriptObject&lt;/span&gt; jsObject = (&lt;span style=&quot;color: teal;&quot;&gt;JavaScriptObject&lt;/span&gt;)jsArray[3];&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt; &lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color: teal;&quot;&gt;Console&lt;/span&gt;.WriteLine(jsObject[&lt;span style=&quot;color: maroon;&quot;&gt;&quot;property&quot;&lt;/span&gt;]);&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color: green;&quot;&gt;// value&lt;/span&gt;&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt; &lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color: teal;&quot;&gt;StringWriter&lt;/span&gt; sw = &lt;span style=&quot;color: blue;&quot;&gt;new&lt;/span&gt; &lt;span style=&quot;color: teal;&quot;&gt;StringWriter&lt;/span&gt;();&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt; &lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color: blue;&quot;&gt;using&lt;/span&gt; (&lt;span style=&quot;color: teal;&quot;&gt;JsonWriter&lt;/span&gt; jsonWriter = &lt;span style=&quot;color: blue;&quot;&gt;new&lt;/span&gt; &lt;span style=&quot;color: teal;&quot;&gt;JsonWriter&lt;/span&gt;(sw))&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;{&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;    serializer.Serialize(sw, jsArray);&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;}&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt; &lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color: teal;&quot;&gt;Console&lt;/span&gt;.WriteLine(sw.GetStringBuilder().ToString());&lt;/pre&gt;&lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color: green;&quot;&gt;// [&#39;JSON!&#39;,1,true,{property:&#39;value&#39;}]&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;strong&gt;&lt;a href=&quot;http://www.newtonsoft.com/products/json/&quot; target=&quot;_blank&quot;&gt;Json.NET&lt;/a&gt;&lt;/strong&gt; - Json.NET Homepage&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;a href=&quot;http://www.newtonsoft.com/downloads/json/json.zip&quot;&gt;Download Json.NET&lt;/a&gt;&lt;/strong&gt; - Json.NET dll and C# source code    &lt;/div&gt; &lt;/div&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;octopus east java baker&lt;/div&gt;</description><link>http://scriptster.blogspot.com/2007/12/jsonnet-simplifying-net-javascript.html</link><author>noreply@blogger.com (Octopus)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-2977499297091575918.post-3372377627459592423</guid><pubDate>Fri, 14 Dec 2007 14:17:00 +0000</pubDate><atom:updated>2007-12-14T06:21:10.616-08:00</atom:updated><title>Json.NET</title><description>&lt;p  style=&quot;color: rgb(102, 102, 102); padding-top: 0pt; margin-top: 0pt;font-size:1em;&quot;&gt;&lt;span&gt;&lt;span id=&quot;ctl00_Main_InlineTagEditorPanel_ctl01&quot;&gt;&lt;a href=&quot;http://james.newtonking.com/archive/tags/Project/default.aspx&quot; rel=&quot;tag&quot;&gt;&lt;/a&gt;&lt;/span&gt;&lt;input name=&quot;ctl00$Main$InlineTagEditorPanel$ctl01&quot; id=&quot;ctl00_Main_InlineTagEditorPanel_ctl01_State&quot; value=&quot;value:Filed%20under%3A%20%3Ca%20href%3D%22%2Farchive%2Ftags%2FJson.NET%2Fdefault.aspx%22%20rel%3D%22tag%22%3EJson.NET%3C%2Fa%3E%2C%20%3Ca%20href%3D%22%2Farchive%2Ftags%2FProject%2Fdefault.aspx%22%20rel%3D%22tag%22%3EProject%3C%2Fa%3E&quot; type=&quot;hidden&quot;&gt;&lt;/span&gt;                                                                                                 &lt;/p&gt;         &lt;p&gt;The Json.NET library makes working with JavaScript and JSON formatted data in .NET simple. Quickly read and write JSON using the JsonReader and JsonWriter or serialize your .NET objects with a single method call using the JsonSerializer. &lt;/p&gt;&lt;p&gt;&lt;b&gt;&lt;a href=&quot;http://www.codeplex.com/json&quot; target=&quot;_blank&quot; mce_href=&quot;http://www.codeplex.com/json&quot;&gt;Json.NET CodePlex Project&lt;/a&gt;&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;&lt;a href=&quot;http://www.codeplex.com/json/Release/ProjectReleases.aspx&quot; target=&quot;_blank&quot; mce_href=&quot;http://www.codeplex.com/json/Release/ProjectReleases.aspx&quot;&gt;Json.NET Download&lt;/a&gt;&lt;/b&gt;&lt;/p&gt;  &lt;p&gt;&lt;b&gt;Features&lt;/b&gt;&lt;/p&gt;  &lt;ul&gt;&lt;li&gt;&lt;span id=&quot;ctl00_ctl00_ctl00_Content_ProjectBaseMain_ProjectMain_wikiSourceLabel&quot;&gt;Lightning fast JsonReader and JsonWriter&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span id=&quot;ctl00_ctl00_ctl00_Content_ProjectBaseMain_ProjectMain_wikiSourceLabel&quot;&gt;The JsonSerializer for quickly converting your .NET objects to JSON and back again&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span id=&quot;ctl00_ctl00_ctl00_Content_ProjectBaseMain_ProjectMain_wikiSourceLabel&quot;&gt;Json.NET can optionally produce well formatted, indented JSON for debugging or display&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span id=&quot;ctl00_ctl00_ctl00_Content_ProjectBaseMain_ProjectMain_wikiSourceLabel&quot;&gt;Attributes like JsonIgnore and JsonProperty can be added to a class to customize how a class is serialized&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span id=&quot;ctl00_ctl00_ctl00_Content_ProjectBaseMain_ProjectMain_wikiSourceLabel&quot;&gt;Ability to convert JSON to and from XML&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;  &lt;p&gt;&lt;b&gt;Example&lt;/b&gt;&lt;/p&gt; &lt;div class=&quot;overflowpanel&quot;&gt; &lt;div class=&quot;code&quot;&gt; &lt;div    style=&quot;background: white none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;font-family:Courier New;font-size:9pt;color:black;&quot;&gt; &lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color: rgb(43, 145, 175);&quot;&gt;Product&lt;/span&gt; product = &lt;span style=&quot;color:blue;&quot;&gt;new&lt;/span&gt; &lt;span style=&quot;color: rgb(43, 145, 175);&quot;&gt;Product&lt;/span&gt;();&lt;/pre&gt; &lt;pre style=&quot;margin: 0px;&quot;&gt;product.Name = &lt;span style=&quot;color: rgb(163, 21, 21);&quot;&gt;&quot;Apple&quot;&lt;/span&gt;;&lt;/pre&gt; &lt;pre style=&quot;margin: 0px;&quot;&gt;product.Expiry = &lt;span style=&quot;color:blue;&quot;&gt;new&lt;/span&gt; &lt;span style=&quot;color: rgb(43, 145, 175);&quot;&gt;DateTime&lt;/span&gt;(2008, 12, 28);&lt;/pre&gt; &lt;pre style=&quot;margin: 0px;&quot;&gt;product.Price = 3.99M;&lt;/pre&gt; &lt;pre style=&quot;margin: 0px;&quot;&gt;product.Sizes = &lt;span style=&quot;color:blue;&quot;&gt;new&lt;/span&gt; &lt;span style=&quot;color:blue;&quot;&gt;string&lt;/span&gt;[] { &lt;span style=&quot;color: rgb(163, 21, 21);&quot;&gt;&quot;Small&quot;&lt;/span&gt;, &lt;span style=&quot;color: rgb(163, 21, 21);&quot;&gt;&quot;Medium&quot;&lt;/span&gt;, &lt;span style=&quot;color: rgb(163, 21, 21);&quot;&gt;&quot;Large&quot;&lt;/span&gt; };&lt;/pre&gt; &lt;pre style=&quot;margin: 0px;&quot;&gt; &lt;/pre&gt; &lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:blue;&quot;&gt;string&lt;/span&gt; json = &lt;span style=&quot;color: rgb(43, 145, 175);&quot;&gt;JavaScriptConvert&lt;/span&gt;.SerializeObject(product);&lt;/pre&gt; &lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:green;&quot;&gt;//{&lt;/span&gt;&lt;/pre&gt; &lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:green;&quot;&gt;//  &quot;Name&quot;: &quot;Apple&quot;,&lt;/span&gt;&lt;/pre&gt; &lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:green;&quot;&gt;//  &quot;Expiry&quot;: new Date(1230422400000),&lt;/span&gt;&lt;/pre&gt; &lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:green;&quot;&gt;//  &quot;Price&quot;: 3.99,&lt;/span&gt;&lt;/pre&gt; &lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:green;&quot;&gt;//  &quot;Sizes&quot;: [&lt;/span&gt;&lt;/pre&gt; &lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:green;&quot;&gt;//    &quot;Small&quot;,&lt;/span&gt;&lt;/pre&gt; &lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:green;&quot;&gt;//    &quot;Medium&quot;,&lt;/span&gt;&lt;/pre&gt; &lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:green;&quot;&gt;//    &quot;Large&quot;&lt;/span&gt;&lt;/pre&gt; &lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:green;&quot;&gt;//  ]&lt;/span&gt;&lt;/pre&gt; &lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color:green;&quot;&gt;//}&lt;/span&gt;&lt;/pre&gt; &lt;pre style=&quot;margin: 0px;&quot;&gt; &lt;/pre&gt; &lt;pre style=&quot;margin: 0px;&quot;&gt;&lt;span style=&quot;color: rgb(43, 145, 175);&quot;&gt;Product&lt;/span&gt; deserializedProduct = &lt;span style=&quot;color: rgb(43, 145, 175);&quot;&gt;JavaScriptConvert&lt;/span&gt;.DeserializeObject&lt;&lt;span style=&quot;color: rgb(43, 145, 175);&quot;&gt;Product&lt;/span&gt;&gt;(json);&lt;/pre&gt; &lt;/div&gt;  &lt;/div&gt; &lt;/div&gt;  &lt;p&gt;&lt;b&gt;History &lt;/b&gt;&lt;/p&gt;  &lt;p&gt;Json.NET grew out of projects I was working on in late 2005 involving JavaScript, AJAX and .NET. At the time there were no libraries for working with JavaScript in .NET so I began to grow my own.&lt;/p&gt;&lt;p&gt;Starting out as a couple of static methods for escaping JavaScript strings, Json.NET evolved as features were added. To add support for reading JSON a major refactor was required and Json.NET will split into the three major classes it still uses today, JsonReader, JsonWriter and JsonSerializer.&lt;br /&gt;&lt;/p&gt;  Json.NET was first released in June 2006. Since then Json.NET has been downloaded thousands of times by developers and is used in a number of major projects open source projects such as &lt;a href=&quot;http://www.castleproject.org/monorail/index.html&quot; target=&quot;_blank&quot; mce_href=&quot;http://www.castleproject.org/monorail/index.html&quot;&gt;MonoRail&lt;/a&gt;, Castle Project&#39;s MVC web framework, and &lt;a href=&quot;http://www.mono-project.com/&quot; target=&quot;_blank&quot; mce_href=&quot;http://www.mono-project.com/&quot;&gt;Mono&lt;/a&gt;, an open source implementation of the .NET framework.&lt;div class=&quot;blogger-post-footer&quot;&gt;octopus east java baker&lt;/div&gt;</description><link>http://scriptster.blogspot.com/2007/12/jsonnet.html</link><author>noreply@blogger.com (Octopus)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-2977499297091575918.post-2245148681402142070</guid><pubDate>Wed, 05 Dec 2007 07:44:00 +0000</pubDate><atom:updated>2007-12-04T23:47:57.445-08:00</atom:updated><title>C# and .Net on Linux</title><description>&lt;p class=&quot;body&quot; align=&quot;left&quot;&gt;&lt;i&gt;Compile and run C# command line and GUI applications on Linux&lt;/i&gt;&lt;/p&gt;  &lt;span class=&quot;body&quot;&gt;&lt;a href=&quot;mailto:shekharg@cmil.com&quot;&gt;Shekhar Govindarajan&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;p&gt;In the past issues of PCQuest we have talked much about MS .Net and C# programming language. .Net and its programming languages (C#, VB .Net, VC++ .Net, Visual J#, Python .Net, Perl .Net, COBOL .Net, etc) are available for only the Windows platform�Win 9x, ME, NT, 2000, XP, Win CE (for portables), etc. But a project named Mono has been introduced now. This is an effort to port .Net and its languages. As of now only C# has been ported to non-Windows platforms. &lt;/p&gt; &lt;p&gt;Libraries, compiler/interpreter and a runtime environment are the three essentials to write and run a program on a platform (OS + hardware architecture). Libraries make the writing of large programs easy by providing commonly-used routines in the form of classes and methods (functions). The .Net framework also has a number of libraries called class libraries. The compiler and the runtime are needed to convert a program into an executable and to run this executable respectively. &lt;/p&gt; &lt;p&gt;Mono packages the port of .Net library classes, a C# compiler and the .Net runtime�CLR (Common Language Runtime).&lt;/p&gt; &lt;p&gt;&lt;img src=&quot;http://www.pcquest.com/images/imagebrowser_aug2k2.jpg&quot; alt=&quot;A graphical Image browser applications in C# running on Linux&quot; align=&quot;right&quot; border=&quot;0&quot; height=&quot;170&quot; hspace=&quot;5&quot; vspace=&quot;5&quot; width=&quot;238&quot; /&gt;Mono claims to run on Linux, Solaris, FreeBSD and MS Windows. And besides the Intel x86 processors (486, Pentiums), it is said to support Sparc, PowerPC and StrongArm processors too. &lt;/p&gt; &lt;p&gt;Without getting into more theory, let�s see how Mono works on Linux. We�ll install Mono on PCQLinux 7.1, compile some C# programs and execute them. We are assuming that you are familiar with the .Net framework and the basics of C#. &lt;/p&gt; &lt;p&gt;&lt;b&gt;Installation&lt;/b&gt;&lt;br /&gt;Mount this month�s PCQuest CD and change to the directory system/cdrom/unltdos/linux/mono. Install all the RPMs found in this directory as&lt;/p&gt; &lt;p&gt;&lt;span style=&quot;color:#0000ff;&quot;&gt;rpm  -ivh  *.rpm&lt;/span&gt;&lt;/p&gt; &lt;p&gt;Among other RPMs required by Mono, the Mono RPM named mono-0.12_baselabs-20020709.i386.rpm gets installed. The basic .Net assemblies like System.Data.dll, System.dll, System.Drawing.dll, System.Web.dll and System.Xml.dll are copied to the directory /usr/lib. &lt;/p&gt; &lt;p&gt;Now, type in the following program in a Linux text editor and save the file as HelloMono.cs.&lt;/p&gt; &lt;p&gt;&lt;br /&gt;&lt;span style=&quot;color:#0000ff;&quot;&gt;class HelloMono&lt;br /&gt;{&lt;br /&gt;  public static void Main(string[ ] args)&lt;br /&gt;   {  System.Console.WriteLine(�Hello Mono�);&lt;br /&gt;   }&lt;br /&gt;}&lt;/span&gt;&lt;/p&gt; &lt;p&gt;&lt;b&gt;Compile the program as&lt;/b&gt;&lt;/p&gt; &lt;p&gt;&lt;span style=&quot;color:#0000ff;&quot;&gt;mcs   HelloMono.cs&lt;/span&gt;&lt;/p&gt; &lt;p&gt;Mcs is the Mono C# command-line compiler. It has many command-line options like the csc compiler of MS .Net SDK. The above command will produce an executable named HelloMono. exe. Note that this executable is not a Linux executable but a .Net executable, technically called the IL (Intermediate Language) code. To run this executable, issue the following.&lt;/p&gt; &lt;p&gt;&lt;span style=&quot;color:#0000ff;&quot;&gt;mono HelloMono.exe&lt;/span&gt;&lt;/p&gt; &lt;p&gt;You will see �Hello Mono� displayed on the Linux console. For more on mcs and Mono, refer to their man pages, which can be brought up by issuing:&lt;/p&gt; &lt;p&gt;&lt;span style=&quot;color:#0000ff;&quot;&gt;man mcs&lt;br /&gt;man mono&lt;/span&gt;&lt;/p&gt; &lt;p&gt;&lt;b&gt;GUI on Mono&lt;br /&gt;&lt;/b&gt;Mono does not support Windows Forms for GUI widgets. However, GTK# (a C# binding of GTK+graphical library) can be used for coding GUI components in C#. You�ll find all the requisites for installing GTK# on the CD. Let�s first install it and then execute some sample GTK# programs. &lt;/p&gt; &lt;p&gt;Change to the directory system/cdrom/unltdos/linux/gtksharp/dep on the CD and install the RPMs as&lt;/p&gt; &lt;p&gt;&lt;span style=&quot;color:#0000ff;&quot;&gt;rpm -Uvh *.rpm --nodeps&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Copy the file named gtk-sharp-0.2.1.tar.gz found in the directory system/cdrom/unltdoss/ linux/gtksharp to /opt directory. Extract the archive as&lt;/p&gt; &lt;p&gt;&lt;span style=&quot;color:#0000ff;&quot;&gt;tar �zxvf gtk-sharp-0.2.1.tar.gz&lt;/span&gt;&lt;/p&gt; &lt;p&gt;This will produce a directory named gtk-sharp-0.2.1 within /opt. Change to this directory and issue&lt;/p&gt; &lt;p&gt;&lt;span style=&quot;color:#0000ff;&quot;&gt;./configure --prefix=/usr&lt;br /&gt;make&lt;br /&gt;make install&lt;/span&gt;&lt;/p&gt; &lt;table align=&quot;right&quot; border=&quot;0&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; width=&quot;55%&quot;&gt;   &lt;tbody&gt;&lt;tr&gt;     &lt;td valign=&quot;top&quot;&gt; &lt;table bg border=&quot;0&quot; cellpadding=&quot;2&quot; cellspacing=&quot;1&quot; width=&quot;100%&quot; style=&quot;color:#000080;&quot;&gt;   &lt;tbody&gt;&lt;tr&gt;     &lt;td bg valign=&quot;top&quot; style=&quot;color:#ff0000;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family:Verdana;font-size:85%;color:#ffffff;&quot;&gt;Monkey Business&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;   &lt;/tr&gt;   &lt;tr&gt;     &lt;td bg valign=&quot;top&quot; style=&quot;color:#ccffcc;&quot;&gt;&lt;span style=&quot;font-family:Verdana;font-size:78%;&quot;&gt;&lt;b&gt;Money wise with Mono:&lt;/b&gt; .Net development can take place on a low-cost non-Windows platform like Linux. The deployment platform can be either Linux or Windows, with the OS cost (per user, per system licenses) in Windows concerning only the end user and not the developer. &lt;/span&gt;       &lt;p&gt;&lt;span style=&quot;font-family:Verdana;font-size:78%;&quot;&gt;Consider the scenario of a client-server .Net application. A user will interact only with the client (which should hopefully be a pleasant-looking GUI application) and expect a familiar platform like Windows. It will not matter to him if the server part is on Windows or Linux. So, the server part can be deployed on a Linux server using Mono, saving on the cost of setting up a dedicated Windows server. &lt;/span&gt;&lt;/p&gt;       &lt;p&gt;&lt;span style=&quot;font-family:Verdana;font-size:78%;&quot;&gt;&lt;b&gt;Easy migration:&lt;/b&gt; If Mono comes out well, Windows developers, too, can develop for Linux and other non-Windows platforms. It won�t be a surprise if later a free or low-cost .Net IDE (Integrated Development Environment) like Visual Studio .Net makes a debut for Linux. &lt;/span&gt;&lt;/p&gt;       &lt;p&gt;&lt;span style=&quot;font-family:Verdana;font-size:78%;&quot;&gt;Linux developers, who should already have a grip of C/C++, can learn C# with similar syntax and constructs as in C/C++. Or, they can wait for a Mono C++ compiler that would give them an easier migration path. &lt;/span&gt;&lt;/p&gt;       &lt;p&gt;&lt;span style=&quot;font-family:Verdana;font-size:78%;&quot;&gt;The success of all this depends upon how well Mono is developed and how close and compatible it is with the implementation of the .Net framework on Windows. Other key factors will be its performance and the look-and-feel of its GUI components. &lt;/span&gt;&lt;/p&gt;       &lt;p&gt;&lt;span style=&quot;font-family:Verdana;font-size:78%;&quot;&gt;If you�re wondering what the title Monkey Business means, here�s the mystery unraveled�Mono means monkey in Spanish. &lt;/span&gt;&lt;/p&gt;&lt;/td&gt;   &lt;/tr&gt;  &lt;/tbody&gt;&lt;/table&gt; &lt;/td&gt;   &lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt; &lt;p&gt;All the assemblies related to GTK# (gtk-sharp.dll, atk-sharp.dll, gdk-sharp.dll, glib-sharp.dll and pango-sharp.dll) are copied to the directory /usr/lib. You will need to refer to them using the �r option (see below) when you compile a C# program that uses GTK# for GUI. Reboot the machine once before proceeding further.&lt;/p&gt; &lt;p&gt;You�ll find some GTK# sample programs (HelloWorld.cs, Menu. cs, ButtonApp.cs) in the directory /opt/gtk-sharp-0.2.1/sample. You can compile them as&lt;/p&gt; &lt;p&gt;&lt;span style=&quot;color:#0000ff;&quot;&gt;mcs -r gtk-sharp -r glib-sharp HelloWorld.cs&lt;/span&gt;&lt;/p&gt; &lt;p&gt;&lt;span style=&quot;color:#0000ff;&quot;&gt;mcs -r gtk-sharp -r glib-sharp -r System.Drawing Menu.cs&lt;/span&gt;&lt;/p&gt; &lt;p&gt;&lt;span style=&quot;color:#0000ff;&quot;&gt;mcs -r gtk-sharp -r glib-sharp -r System.Drawing ButtonApp.cs&lt;/span&gt;&lt;/p&gt; &lt;p&gt;Note how we are referring to the various assemblies using the �r option. Next, start X Window using the startx command and from within a terminal window, change (cd) to the directory /opt/gtk-sharp-0.2.1/sample and issue the following commands to execute the respective programs.&lt;/p&gt; &lt;p&gt;&lt;span style=&quot;color:#0000ff;&quot;&gt;mono   HelloWorld.exe&lt;br /&gt;mono  Menu.exe&lt;br /&gt;mono ButtonApp.exe&lt;/span&gt;&lt;/p&gt; &lt;p&gt;Since Mono is an ongoing project and not all the .Net class libraries have been ported, you may find some quirks with it. Nevertheless, it�s usable to a great extent. You can check out the port status of class libraries at www.go-mono.com/class-status.html. For more on Mono, go to www.go-mono.com. For more on GTK#, see http://gtk-sharp. sourceforge.&lt;/p&gt; &lt;p&gt;Net/. &lt;/p&gt; &lt;p&gt;Shekhar Govindarajan&lt;/p&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;octopus east java baker&lt;/div&gt;</description><link>http://scriptster.blogspot.com/2007/12/c-and-net-on-linux.html</link><author>noreply@blogger.com (Octopus)</author><thr:total>1</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-2977499297091575918.post-1301279332153841055</guid><pubDate>Wed, 05 Dec 2007 07:39:00 +0000</pubDate><atom:updated>2007-12-04T23:41:50.544-08:00</atom:updated><title>Running .Net applications on Linux with Mono</title><description>Imagine the fate of your company rests on your completing your new Linux project on time. You have a crack team of first-class developers, but they&#39;re all .Net programmers. What are you going to do? Admit that Windows is better that Linux? Cry? Resign? No, you&#39;re going to install &lt;a href=&quot;http://www.mono-project.com/Main_Page&quot;&gt;Mono &lt;/a&gt; and save the world!&lt;br /&gt;&lt;p&gt;Mono is an open source project (sponsored by &lt;a href=&quot;http://www.novell.com/&quot;&gt;Novell &lt;/a&gt;) that allows you to run .Net applications on Linux (as well as Unix, Mac OS X, Solaris and even Windows). To obtain it, go to the &lt;a href=&quot;http://www.mono-project.com/Downloads&quot;&gt;Mono download page &lt;/a&gt; and find the version you need for your distro. &lt;/p&gt;&lt;br /&gt;&lt;p&gt;Once you&#39;ve installed Mono, get one of your .Net programmers to create and compile a simple Microsoft Visual Studio C# console application. Just something easy, such as: &lt;/p&gt;&lt;br /&gt;using System; namespace ConsoleApplication1 { class Program { static void Main(string[] args) { Console.WriteLine(&quot;Hello World&quot;); } } }&lt;br /&gt;&lt;table&gt;&lt;br /&gt;  &lt;tr&gt;&lt;br /&gt;    &lt;td&gt;If you don&#39;t have your own tame .Net programmer, you&#39;re going to need a Windows machine with Microsoft Visual Studio installed. (Stop making faces like that!) Download the free &lt;a href=&quot;http://msdn.microsoft.com/vstudio/express/visualcsharp/download/&quot;&gt;Microsoft Visual C# Express Edition &lt;/a&gt;. &lt;/td&gt;&lt;br /&gt;  &lt;/tr&gt;&lt;br /&gt;&lt;/table&gt;&lt;br /&gt;&lt;p&gt;Transfer the compiled application from the Windows machine by using FTP or Samba, then log on to your Linux box and run the application: &lt;/p&gt;&lt;br /&gt;&lt;p&gt;$ ConsoleApplication1.exe Hello World &lt;/p&gt;&lt;br /&gt;&lt;p&gt;Surely it can&#39;t be as simple as that? Amazingly, it is. If you don&#39;t believe that it&#39;s Mono that&#39;s allowing you to do this, try transferring the application to a Linux box that hasn&#39;t got Mono installed. You&#39;ll get a result something like: &lt;/p&gt;&lt;br /&gt;&lt;p&gt;$ ConsoleApplication1.exe &lt;br&gt;&lt;br /&gt;  -bash: ./ConsoleApplication1.exe: cannot execute binary file &lt;/p&gt;&lt;br /&gt;&lt;table&gt;&lt;br /&gt;  &lt;tr&gt;&lt;br /&gt;    &lt;td&gt;&lt;p&gt;You may need to run chmod +x on the file to get it to run. Also, I found that on Debian at this stage I got an error: The assembly mscorlib.dll was not found or could not be loaded. It should have been installed in the &#39;/usr/lib/mono/2.0/mscorlib.dll&#39; directory. I cured that by executing: &lt;/p&gt;&lt;br /&gt;      $ cd /usr/lib/mono $ sudo ln -s 1.0 2.0 &lt;/td&gt;&lt;br /&gt;  &lt;/tr&gt;&lt;br /&gt;&lt;/table&gt;&lt;br /&gt;&lt;p&gt;The application name ends in .exe because it has been compiled as a Windows application. Once you&#39;ve got it on Linux you can of course call it whatever you want: &lt;/p&gt;&lt;br /&gt;$ mv ConsoleApplication1.exe HelloWorld $ HelloWorld Hello World&lt;br /&gt;&lt;p&gt;You&#39;ve just seen just how easy is to use a Microsoft Visual Studio application on Linux. However, you&#39;re also probably thinking that you have absolutely no intention of using Windows at all; your .Net programmers are just going to have to have to learn to program in something that runs solely on Linux. That&#39;s a good idea -- if you&#39;ve got the time for them to learn something new. If not, don&#39;t despair. Mono comes with its own .Net compiler, mcs. To us it, paste the code for the &#39;Hello World&#39; application above into a file, compile it (using mcs), then run the new application from the command line. &lt;/p&gt;&lt;br /&gt;$ mcs -out:HelloWorld.exe Program.cs $ HelloWorld.exe Hello World&lt;br /&gt;&lt;p&gt;If you&#39;ve still got that Windows machine fired up, you may find it interesting to transfer the newly compiled application to it and running your app in Windows. You&#39;ll find that you&#39;ve created something on Linux that will also run on Windows. &lt;/p&gt;&lt;br /&gt;&lt;p&gt;Of course, by the time you&#39;ve explained all this to your .Net programmers they&#39;ll be up in arms. &quot;How can you expect us to program without a pretty GUI?&quot; they&#39;ll cry. &lt;/p&gt;&lt;br /&gt;&lt;p&gt;&quot;With &lt;a href=&quot;http://www.monodevelop.com/Main_Page&quot;&gt;Monodevelop &lt;/a&gt;,&quot; you&#39;ll say, referring to Mono&#39;s integrated development environment (IDE). With Monodevelop your developers can happily work with Glade#, Gnome#, and GTK#, all within a .Net-type environment. Check the software&#39;s &lt;a href=&quot;http://www.monodevelop.com/Download&quot;&gt;download page &lt;/a&gt; for your distro&#39;s version and any dependencies. &lt;/p&gt;&lt;br /&gt;&lt;table&gt;&lt;br /&gt;  &lt;tr&gt;&lt;br /&gt;    &lt;td&gt;When you install Glade, make sure that you obtain Glade2 and not Glade1. On Debian sudo apt-get install glade will grab Glade1, which will not work with Monodevelop. The correct installation command is sudo apt-get install glade-2 . &lt;/td&gt;&lt;br /&gt;  &lt;/tr&gt;&lt;br /&gt;&lt;/table&gt;&lt;br /&gt;&lt;p&gt;The developers should leave you in peace for a while, but they&#39;ll be back. &quot;Where&#39;s the GUI designer?&quot; they&#39;ll ask. This is where you introduce them to building interfaces with &lt;a href=&quot;http://glade.gnome.org/&quot;&gt;Glade &lt;/a&gt;. When you start a new Monodevelop Glade# application, use a file called gui.glade . You can edit this with Glade and then do the programming in Monodevelop. If your developers have any further questions, point them in the direction of &lt;a href=&quot;http://www.mono-project.com/GtkSharpBeginnersGuide&quot;&gt;the Mono GTK# Beginner&#39;s Guide &lt;/a&gt;. &lt;/p&gt;&lt;br /&gt;&lt;p&gt;With your .Net programmers happily producing applications for Linux, you can turn your attention to ASP .Net for building Web applications. You&#39;re going to need a Web server, which can be either Apache (with mod_mono installed) or Mono&#39;s own Web server, XSP. Have a look at the &lt;a href=&quot;http://www.gotmono.com/docs/aspnet/installation.html&quot;&gt;Mono Handbook page for Web sites and Web services &lt;/a&gt; to find out how to set up the XSP server. On Debian, for example, its just a matter of installing the software: &lt;/p&gt;&lt;br /&gt;sudo apt-get install mono-xsp&lt;br /&gt;&lt;p&gt;Then running it: &lt;/p&gt;&lt;br /&gt;$ cd mono $ xsp xsp Listening on port: 8080 Listening on address: 0.0.0.0 Root directory: /home/bainm/mono Hit Return to stop the server.&lt;br /&gt;&lt;p&gt;XSP will run in the directory where you start it, will use this as its home directory, and will use port 8080 by default. If you don&#39;t want to have to change into that directory every time you start the server, you can use its --root option. To change the port, use the --port option: &lt;/p&gt;&lt;br /&gt;$ xsp --root ~/mono --port 8081&lt;br /&gt;&lt;p&gt;When you&#39;ve got your server up and running, go to &lt;a href=&quot;http://www.mono-project.com/Web_Services&quot;&gt;Mono&#39;s Web Services page &lt;/a&gt;, where you&#39;ll find some good examples of the types of services that you can start running. However, if you&#39;re desperate to see the server in action, go to the directory you&#39;re running XSP from and cat the following into index.aspx: &lt;/p&gt;&lt;br /&gt;&amp;lt;%@ Page Language=&quot;C#&quot; %&amp;gt; &amp;lt;html&amp;gt;&amp;lt;body&amp;gt; &amp;lt;% &amp;nbsp;&amp;nbsp;&amp;nbsp; Response.Output.Write(&quot;Hello World!&quot;); %&amp;gt; &amp;lt;/body&amp;gt; &amp;lt;/html&amp;gt;&lt;br /&gt;&lt;p&gt;Now open up a Web browser and type in the URL of your host (plus the port number) -- e.g. http://hector:8080 . Granted, this isn&#39;t the most exciting example in the world, but it proves that you can run ASP .Net on Linux. A quick search on Google will give you a host of other examples that you can use. &lt;/p&gt;&lt;br /&gt;&lt;p&gt;With Mono, Monodevelop, and XSP in place, you can throw away Microsoft Visual Studio and you can throw away Windows, and you don&#39;t have to throw away the valued experience of your .Net programmers. &lt;/p&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;octopus east java baker&lt;/div&gt;</description><link>http://scriptster.blogspot.com/2007/12/running-net-applications-on-linux-with.html</link><author>noreply@blogger.com (Octopus)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-2977499297091575918.post-7175882682748033855</guid><pubDate>Wed, 05 Dec 2007 07:35:00 +0000</pubDate><atom:updated>2007-12-04T23:39:00.710-08:00</atom:updated><title>Mono 1.0 Brings Linux .Net-Style Development</title><description>&lt;span class=&quot;authorsource&quot;&gt;By&lt;/span&gt; &lt;a href=&quot;http://www.eweek.com/author_bio/0,1908,a=2294,00.asp&quot; class=&quot;authorsource&quot;&gt;Jason Brooks&lt;/a&gt;   &lt;br /&gt;&lt;br /&gt;&lt;p&gt;Novell Inc.&#39;s Mono 1.0 is an open-source implementation of Microsoft Corp.&#39;s .Net development platform that provides companies with the opportunity to pursue the latest Microsoft development technologies while leaving open the door to cross-platform support.&lt;/p&gt; &lt;p&gt;While the .Net Framework targets only Windows, Mono 1.0 supports Linux and Unix platforms, as well as systems running Windows and Mac OS X.&lt;/p&gt; &lt;p&gt;Mono comprises a compiler for the C# programming language, a run-time engine for Microsoft&#39;s Common Language Infrastructure and a group of .Net-compatible class libraries that are required for running .Net applications with Mono. These libraries include open-source versions of Microsoft&#39;s ADO.Net data access and ASP.Net Web application development technologies.&lt;/p&gt;  &lt;p&gt;&lt;!-- start ziffimage //--&gt;&lt;!-- end ziffimage //--&gt;&lt;!-- start ziffarticle //--&gt;&lt;a href=&quot;http://www.eweek.com/article2/0,1895,1627301,00.asp&quot; class=&quot;NAVELEMENT&quot;&gt;There have been rumors that Microsoft may open-source the Common Language Runtime component of .Net. &lt;u&gt;Click here&lt;/u&gt; to read more.&lt;/a&gt;&lt;!-- end ziffarticle //--&gt;   &lt;/p&gt;&lt;p&gt;Using the mod_mono Apache Web server module that ships with Mono 1.0, sites can serve ASP.Net pages with Apache on Linux (the module doesn&#39;t support Apache on Windows). This means that companies can make development and production platform choices separately.&lt;/p&gt; &lt;p&gt;Perhaps more important than Mono 1.0&#39;s ability to bring certain Windows applications to Linux is that it brings the .Net development model to Linux. A variety of class libraries for developing native Linux applications are included along with Mono&#39;s .Net compatibility libraries.&lt;/p&gt; &lt;p&gt;In eWEEK Labs&#39; tests, for example, we were able to quickly create a simple Web browser in C#, with a GUI based on the Gtk framework and rendering handled by Mozilla&#39;s Gecko engine.&lt;/p&gt; &lt;p&gt;Although Mono 1.0 is intended to provide full compatibility with pure .Net Version 1.1 applications, .Net applications that make use of native Windows APIs will require porting work to be brought over to Linux.&lt;/p&gt; &lt;p&gt;Applications that use Microsoft&#39;s WinForms rich user interface classes, which depend on native Windows system calls, can run with Mono using a library based on Wine that ships along with Mono.&lt;/p&gt; &lt;p&gt;Mono 1.0 ships with MonoDevelop, a port of the open-source .Net IDE (integrated development environment) SharpDevelop to Gtk#. MonoDevelop doesn&#39;t handle GUI creation—for that, we used the Gtk interface tool Glade.&lt;/p&gt; &lt;p&gt;Mono also includes a documentation browser. We were impressed with the breadth of Mono&#39;s documentation, which includes lots of sample projects.&lt;/p&gt; &lt;p&gt;Mono&#39;s compiler supports C#, and a Mono compiler for Microsoft&#39;s Visual Basic .Net, called MBas, is under development.&lt;/p&gt; &lt;p&gt;Mono ships with IKVM, a Mono-based Java virtual machine, plus implementations of Java class libraries based on work from the open-source project Classpath. IKVM enables sites to run Java applications with Mono and use Java libraries in .Net applications.&lt;/p&gt; &lt;p&gt;Mono 1.0 is available for free download in source code form at &lt;a href=&quot;http://www.mono-project.com/downloads&quot;&gt;www.mono-project.com/downloads.&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Mono&#39;s run-time engine supports the x86, x86-64, PowerPC, SPARC, S390, StrongARM and HPPA processor architectures on Linux, Windows, HP-UX, Solaris, Mac OS and BSD operating systems. Mono also ships with a native optimizing compiler in both ahead-of-time and just-in-time compilation modes for the x86, SPARC, S390 and PowerPC architectures.&lt;/p&gt; &lt;p&gt;Precompiled, ready-to-install packages are also available through this site for Red Hat Linux 9, Fedora Core 1 and 2, SuSE Linux Enterprise Server 8, SuSE Linux 9.0 and 9.1, Slackware 10, Windows 2000 and above, and Mac OS X Panther.&lt;/p&gt;   &lt;p&gt;&lt;i&gt;Senior Analyst Jason Brooks can be reached at &lt;a href=&quot;mailto:jason_brooks@ziffdavis.com&quot;&gt;jason_brooks@ziffdavis.com.&lt;/a&gt;&lt;/i&gt;&lt;!-- end ziffimage //--&gt;&lt;br /&gt;&lt;/p&gt;&lt;!-- start ziffimage //--&gt;&lt;img src=&quot;http://common.ziffdavisinternet.com/util_get_image/7/0,1425,i=77043,00.gif&quot; alt=&quot;horizontal rule&quot; border=&quot;0&quot; height=&quot;1&quot; width=&quot;400&quot; /&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;octopus east java baker&lt;/div&gt;</description><link>http://scriptster.blogspot.com/2007/12/mono-10-brings-linux-net-style.html</link><author>noreply@blogger.com (Octopus)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-2977499297091575918.post-1447285572268317280</guid><pubDate>Tue, 04 Dec 2007 07:43:00 +0000</pubDate><atom:updated>2007-12-03T23:54:50.931-08:00</atom:updated><title>PHP Webservices and C# / .NET SOAP Clients</title><description>Code Zulu Bind Maker is a project I started working on about 3 years ago. Its a stupid little app that configures game settings for Counter-Strike. When I wrote it, version 1.6 was in beta, and everybody played version 1.5 (which was ever so different). Anyway I run a website that supports the app, and of course, its written in PHP / MySql (my poison of choice on the web).&lt;br /&gt;   &lt;br /&gt;The reason for the boring and seemingly pointless background is that ever since I wrote the app, I always wanted to integrate the website and application, but never really thought of a &quot;good&quot; way to do it. A couple days ago, I had some spare time and sat down to see how easy it would be to create some PHP webservices that I could easily consume in C#. I had been considering expanding the community aspect of the bind maker website into the application so that they&#39;d work seamlessly together. I also wanted to add a common place that gaming communities could spend their time (which I had previously planned for just the website, but was thinking of the possibilities of bringing that into the app as well), and a PHP webservice combined with a C# windows app seemed like the best option.&lt;br /&gt; &lt;br /&gt;C# webservices (server side) are about as easy-as-it-gets to write. C#&#39;s SOAP client is completely transparent (or I should say completely generated so you code just like you would use any other objects) and is completely brainless to use. Since I&#39;d never done webservice work in PHP, I started asking Mr. Google how it worked, and what would you now but that I stumbled across the &lt;a nicetitle=&quot;NuSOAP a SOAP library for PHP&quot; href=&quot;http://sourceforge.net/projects/nusoap/&quot;&gt;NuSOAP&lt;/a&gt; library for php. It sure beat the heck out of writing all my WSDL files by hand, wrapping and unwrapping stupidly simple SOAP messages, and hacking everything very poorly.&lt;br /&gt; &lt;br /&gt;My first PHP webservice iteration was a simple &quot;hello &lt;name&gt; &quot; web method. It used a simple type (xsd:string) as its parameter and returned a simple type (again another xsd:string) as its return value and looked like this: &lt;pre class=&quot;code&quot;&gt; &lt;span class=&quot;php_comments&quot;&gt;/**&lt;br /&gt;* ProcessSimpleType method&lt;br /&gt;* &lt;strong&gt;@param&lt;/strong&gt; string $who name of the person we&#39;ll say hello to&lt;br /&gt;* &lt;strong&gt;@return&lt;/strong&gt; string $helloText the hello &lt;name&gt; string&lt;br /&gt;*/&lt;/name&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt; ProcessSimpleType(&lt;span class=&quot;php_var&quot;&gt;$who&lt;/span&gt;) {&lt;br /&gt; return &lt;span class=&quot;php_string&quot;&gt;&quot;Hello &lt;/span&gt;&lt;span class=&quot;php_var&quot;&gt;$who&lt;/span&gt;&lt;span class=&quot;php_string&quot;&gt;&quot;&lt;/span&gt;;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt; NuSoap was great. It took care of all the nitty-gritty work that I had previously done myself. All it took was about 8 lines of code to set up the SOAP server and register the method and my types.&lt;br /&gt;&lt;pre class=&quot;code&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;require_once&lt;/span&gt;(&lt;span class=&quot;php_string&quot;&gt;&quot;lib/nusoap/nusoap.php&quot;&lt;/span&gt;);&lt;br /&gt;&lt;span class=&quot;php_var&quot;&gt;$namespace&lt;/span&gt; = &lt;span class=&quot;php_string&quot;&gt;&quot;http://sanity-free.org/services&quot;&lt;/span&gt;;&lt;br /&gt;&lt;span class=&quot;php_comments&quot;&gt;// create a new soap server&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;php_var&quot;&gt;$server&lt;/span&gt; = new soap_server();&lt;br /&gt;&lt;span class=&quot;php_comments&quot;&gt;// configure our WSDL&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;php_var&quot;&gt;$server&lt;/span&gt;-&gt;configureWSDL(&lt;span class=&quot;php_string&quot;&gt;&quot;SimpleService&quot;&lt;/span&gt;);&lt;br /&gt;&lt;span class=&quot;php_comments&quot;&gt;// set our namespace&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;php_var&quot;&gt;$server&lt;/span&gt;-&gt;wsdl-&gt;schemaTargetNamespace = &lt;span class=&quot;php_var&quot;&gt;$namespace&lt;/span&gt;;&lt;br /&gt;&lt;span class=&quot;php_comments&quot;&gt;// register our WebMethod&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;php_var&quot;&gt;$server&lt;/span&gt;-&gt;register(&lt;br /&gt;               &lt;span class=&quot;php_comments&quot;&gt;// method name:&lt;/span&gt;&lt;br /&gt;               &lt;span class=&quot;php_string&quot;&gt;&#39;ProcessSimpleType&#39;,&lt;/span&gt;   &lt;br /&gt;               &lt;span class=&quot;php_comments&quot;&gt;// parameter list:&lt;/span&gt;&lt;br /&gt;               &lt;span class=&quot;keyword&quot;&gt;array&lt;/span&gt;(&lt;span class=&quot;php_string&quot;&gt;&#39;name&#39;&lt;/span&gt;=&gt;&lt;span class=&quot;php_string&quot;&gt;&#39;xsd:string&#39;&lt;/span&gt;),&lt;br /&gt;               &lt;span class=&quot;php_comments&quot;&gt;// return value(s):&lt;/span&gt;&lt;br /&gt;               &lt;span class=&quot;keyword&quot;&gt;array&lt;/span&gt;(&lt;span class=&quot;php_string&quot;&gt;&#39;return&#39;&lt;/span&gt;=&gt;&lt;span class=&quot;php_string&quot;&gt;&#39;xsd:string&#39;&lt;/span&gt;),&lt;br /&gt;               &lt;span class=&quot;php_comments&quot;&gt;// namespace:&lt;/span&gt;&lt;br /&gt;               &lt;span class=&quot;php_var&quot;&gt;$namespace&lt;/span&gt;,&lt;br /&gt;               &lt;span class=&quot;php_comments&quot;&gt;// soapaction: (use default)&lt;/span&gt;&lt;br /&gt;               &lt;span class=&quot;keyword&quot;&gt;false&lt;/span&gt;,&lt;br /&gt;               &lt;span class=&quot;php_comments&quot;&gt;// style: rpc or document&lt;/span&gt;&lt;br /&gt;               &lt;span class=&quot;php_string&quot;&gt;&#39;rpc&#39;&lt;/span&gt;,&lt;br /&gt;               &lt;span class=&quot;php_comments&quot;&gt;// use: encoded or literal&lt;/span&gt;&lt;br /&gt;               &lt;span class=&quot;php_string&quot;&gt;&#39;encoded&#39;&lt;/span&gt;,&lt;br /&gt;               &lt;span class=&quot;php_comments&quot;&gt;// description: documentation for the method&lt;/span&gt;&lt;br /&gt;               &lt;span class=&quot;php_string&quot;&gt;&#39;A simple Hello World web method&#39;&lt;/span&gt;);&lt;br /&gt;              &lt;br /&gt;&lt;span class=&quot;php_comments&quot;&gt;// Get our posted data if the service is being consumed&lt;br /&gt;// otherwise leave this data blank. &lt;/span&gt;              &lt;br /&gt;&lt;span class=&quot;php_var&quot;&gt;$POST_DATA&lt;/span&gt; = &lt;span class=&quot;keyword&quot;&gt;isset&lt;/span&gt;(&lt;span class=&quot;php_var&quot;&gt;$GLOBALS&lt;/span&gt;[&lt;span class=&quot;php_string&quot;&gt;&#39;HTTP_RAW_POST_DATA&#39;&lt;/span&gt;])&lt;br /&gt;               ? &lt;span class=&quot;php_var&quot;&gt;$GLOBALS&lt;/span&gt;[&lt;span class=&quot;php_string&quot;&gt;&#39;HTTP_RAW_POST_DATA&#39;&lt;/span&gt;] : &lt;span class=&quot;php_string&quot;&gt;&#39;&#39;&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;php_comments&quot;&gt;// pass our posted data (or nothing) to the soap service&lt;/span&gt;                   &lt;br /&gt;&lt;span class=&quot;php_var&quot;&gt;$server&lt;/span&gt;-&gt;service(&lt;span class=&quot;php_var&quot;&gt;$POST_DATA&lt;/span&gt;);               &lt;br /&gt;&lt;span class=&quot;keyword&quot;&gt;exit&lt;/span&gt;();&lt;/pre&gt; That was it.  From visual studio I was then able to consume the webservice by adding a web reference&lt;br /&gt;&lt;br /&gt;&lt;div class=&quot;big_image&quot;&gt;&lt;img nicetitle=&quot;Add A Web Reference&quot; src=&quot;http://www.sanity-free.org/images/addref.gif&quot; border=&quot;0&quot; /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class=&quot;big_image&quot;&gt;&lt;img nicetitle=&quot;Add A Web Reference&quot; src=&quot;http://www.sanity-free.org/images/refdiag.gif&quot; border=&quot;0&quot; /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class=&quot;big_image&quot;&gt;&lt;img nicetitle=&quot;Add A Web Reference&quot; src=&quot;http://www.sanity-free.org/images/webref.gif&quot; border=&quot;0&quot; /&gt;&lt;/div&gt;&lt;br /&gt;With the reference added, I put a button on my form, and added the following button click event handler:&lt;br /&gt;&lt;!-- readmore --&gt; &lt;pre class=&quot;code&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;private void&lt;/span&gt; button1_Click(&lt;span class=&quot;keyword&quot;&gt;object&lt;/span&gt; sender, &lt;span class=&quot;class_def&quot;&gt;EventArgs&lt;/span&gt; e) {&lt;br /&gt;   &lt;span class=&quot;class_def&quot;&gt;SimpleService&lt;/span&gt; svc = &lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;class_def&quot;&gt;SimpleService&lt;/span&gt;();&lt;br /&gt;   &lt;span class=&quot;keyword&quot;&gt;string&lt;/span&gt; s = svc.ProcessSimpleType(&lt;span class=&quot;string&quot;&gt;&quot;steve&quot;&lt;/span&gt;);&lt;br /&gt;   &lt;span class=&quot;class_def&quot;&gt;MessageBox&lt;/span&gt;.Show(s);&lt;br /&gt;}&lt;/pre&gt; Ran my application, pressed the button (which in turn called the webservice), and voilà I get a message box telling me Hello:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class=&quot;small_image&quot;&gt;&lt;img nicetitle=&quot;Hello Steve Message Box&quot; src=&quot;http://www.sanity-free.org/images/hellosteve.gif&quot; border=&quot;0&quot; /&gt;&lt;/div&gt;&lt;br /&gt;That&#39;s great!  Completely useless, but great!&lt;br /&gt;&lt;br /&gt;Now to get a little more complicated... I had planned on using complex data types that would be consumed by both PHP and .NET clients (A PHP SOAP client for the website, and .NET client for the windows application). It may sound stupid to have a PHP client when most likely I&#39;d have access to the method directly, but the server that is going to host the webservices is actually different than the &quot;web presence&quot; server I host my website on. Anyway, the test complex types I came up needed to look like simple structs (in C#) which would also be used in an array, and they looked something like this:&lt;br /&gt;&lt;pre class=&quot;code&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;public struct&lt;/span&gt; &lt;span class=&quot;class_def&quot;&gt;MySoapObject&lt;/span&gt; {&lt;br /&gt;   &lt;span class=&quot;keyword&quot;&gt;public string&lt;/span&gt; Author;&lt;br /&gt;   &lt;span class=&quot;keyword&quot;&gt;public string&lt;/span&gt; Name;&lt;br /&gt;   &lt;span class=&quot;keyword&quot;&gt;public string &lt;/span&gt;Description;&lt;br /&gt;   &lt;span class=&quot;keyword&quot;&gt;public string&lt;/span&gt; Text;&lt;br /&gt;   &lt;span class=&quot;keyword&quot;&gt;public int&lt;/span&gt; VoteTotal;&lt;br /&gt;   &lt;span class=&quot;keyword&quot;&gt;public int&lt;/span&gt; VoteCount;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;class_def&quot;&gt;MySoapObject&lt;/span&gt;[] soapObjects = &lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;class_def&quot;&gt;MySoapObject&lt;/span&gt;[10];&lt;/pre&gt; so I added the definitions in PHP using NuSOAP like this:&lt;br /&gt;&lt;pre class=&quot;code&quot;&gt;&lt;span class=&quot;php_var&quot;&gt;$server&lt;/span&gt;-&gt;wsdl-&gt;addComplexType(&lt;br /&gt;   &lt;span class=&quot;php_string&quot;&gt;&#39;MySoapObject&#39;&lt;/span&gt;,&lt;br /&gt;   &lt;span class=&quot;php_string&quot;&gt;&#39;complexType&#39;&lt;/span&gt;,&lt;br /&gt;   &lt;span class=&quot;php_string&quot;&gt;&#39;struct&#39;&lt;/span&gt;,&lt;br /&gt;   &lt;span class=&quot;php_string&quot;&gt;&#39;all&#39;&lt;/span&gt;,&lt;br /&gt;   &lt;span class=&quot;php_string&quot;&gt;&#39;&#39;&lt;/span&gt;,&lt;br /&gt;   &lt;span class=&quot;keyword&quot;&gt;array&lt;/span&gt;(&lt;br /&gt;       &lt;span class=&quot;php_string&quot;&gt;&#39;Author&#39;&lt;/span&gt; =&gt; &lt;span class=&quot;keyword&quot;&gt;array&lt;/span&gt;(&lt;span class=&quot;php_string&quot;&gt;&#39;name&#39;&lt;/span&gt;=&gt;&lt;span class=&quot;php_string&quot;&gt;&#39;Author&#39;&lt;/span&gt;,&lt;span class=&quot;php_string&quot;&gt;&#39;type&#39;&lt;/span&gt;=&gt;&lt;span class=&quot;php_string&quot;&gt;&#39;xsd:string&#39;&lt;/span&gt;),&lt;br /&gt;       &lt;span class=&quot;php_string&quot;&gt;&#39;Name&#39;&lt;/span&gt; =&gt; &lt;span class=&quot;keyword&quot;&gt;array&lt;/span&gt;(&lt;span class=&quot;php_string&quot;&gt;&#39;name&#39;&lt;/span&gt;=&gt;&lt;span class=&quot;php_string&quot;&gt;&#39;Name&#39;&lt;/span&gt;,&lt;span class=&quot;php_string&quot;&gt;&#39;type&#39;&lt;/span&gt;=&gt;&lt;span class=&quot;php_string&quot;&gt;&#39;xsd:string&#39;&lt;/span&gt;),&lt;br /&gt;       &lt;span class=&quot;php_string&quot;&gt;&#39;Description&#39;&lt;/span&gt; =&gt; &lt;span class=&quot;keyword&quot;&gt;array&lt;/span&gt;(&lt;span class=&quot;php_string&quot;&gt;&#39;name&#39;&lt;/span&gt;=&gt;&lt;span class=&quot;php_string&quot;&gt;&#39;Description&#39;&lt;/span&gt;,&lt;span class=&quot;php_string&quot;&gt;&#39;type&#39;&lt;/span&gt;=&gt;&lt;span class=&quot;php_string&quot;&gt;&#39;xsd:string&#39;&lt;/span&gt;),&lt;br /&gt;       &lt;span class=&quot;php_string&quot;&gt;&#39;Text&#39;&lt;/span&gt; =&gt; &lt;span class=&quot;keyword&quot;&gt;array&lt;/span&gt;(&lt;span class=&quot;php_string&quot;&gt;&#39;name&#39;&lt;/span&gt;=&gt;&lt;span class=&quot;php_string&quot;&gt;&#39;Text&#39;&lt;/span&gt;,&lt;span class=&quot;php_string&quot;&gt;&#39;type&#39;&lt;/span&gt;=&gt;&lt;span class=&quot;php_string&quot;&gt;&#39;xsd:string&#39;&lt;/span&gt;),&lt;br /&gt;       &lt;span class=&quot;php_string&quot;&gt;&#39;VoteTotal&#39;&lt;/span&gt; =&gt; &lt;span class=&quot;keyword&quot;&gt;array&lt;/span&gt;(&lt;span class=&quot;php_string&quot;&gt;&#39;name&#39;&lt;/span&gt;=&gt;&lt;span class=&quot;php_string&quot;&gt;&#39;VoteTotal&#39;&lt;/span&gt;,&lt;span class=&quot;php_string&quot;&gt;&#39;type&#39;=&gt;&#39;xsd:int&#39;&lt;/span&gt;),&lt;br /&gt;       &lt;span class=&quot;php_string&quot;&gt;&#39;VoteCount&#39;&lt;/span&gt; =&gt; &lt;span class=&quot;keyword&quot;&gt;array&lt;/span&gt;(&lt;span class=&quot;php_string&quot;&gt;&#39;name&#39;&lt;/span&gt;=&gt;&lt;span class=&quot;php_string&quot;&gt;&#39;VoteCount&#39;&lt;/span&gt;,&lt;span class=&quot;php_string&quot;&gt;&#39;type&#39;&lt;/span&gt;=&gt;&lt;span class=&quot;php_string&quot;&gt;&#39;xsd:int&#39;&lt;/span&gt;)&lt;br /&gt;   )&lt;br /&gt;);&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;php_var&quot;&gt;$server&lt;/span&gt;-&gt;wsdl-&gt;addComplexType(&lt;br /&gt;   &lt;span class=&quot;php_string&quot;&gt;&#39;MySoapObjectArray&#39;&lt;/span&gt;,&lt;br /&gt;   &lt;span class=&quot;php_string&quot;&gt;&#39;complexType&#39;&lt;/span&gt;,&lt;br /&gt;   &lt;span class=&quot;php_string&quot;&gt;&#39;array&#39;&lt;/span&gt;,&lt;br /&gt;   &lt;span class=&quot;php_string&quot;&gt;&#39;&#39;&lt;/span&gt;,&lt;br /&gt;   &lt;span class=&quot;php_string&quot;&gt;&#39;SOAP-ENC:Array&#39;&lt;/span&gt;,&lt;br /&gt;   &lt;span class=&quot;keyword&quot;&gt;array&lt;/span&gt;(),&lt;br /&gt;   &lt;span class=&quot;keyword&quot;&gt;array&lt;/span&gt;(&lt;span class=&quot;keyword&quot;&gt;array&lt;/span&gt;(&lt;span class=&quot;php_string&quot;&gt;&#39;ref&#39;&lt;/span&gt;=&gt;&lt;span class=&quot;php_string&quot;&gt;&#39;SOAP-ENC:arrayType&#39;&lt;/span&gt;,&lt;span class=&quot;php_string&quot;&gt;&#39;wsdl:arrayType&#39;&lt;/span&gt;=&gt;&lt;span class=&quot;php_string&quot;&gt;&#39;tns:MySoapObject[]&#39;&lt;/span&gt;)),&lt;br /&gt;   &lt;span class=&quot;php_string&quot;&gt;&#39;tns:MySoapObject&#39;&lt;/span&gt;&lt;br /&gt;);&lt;/pre&gt; I defined the method in PHP that would take in an array of MySoapObjects, process them, and then return one MySoapObject that it had &quot;processed&quot;.&lt;br /&gt;&lt;br /&gt;That method looked like this:&lt;br /&gt;&lt;pre class=&quot;code&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt; ProcessMySoapObject(&lt;span class=&quot;php_var&quot;&gt;$mySoapObjects&lt;/span&gt;) {&lt;br /&gt; &lt;span class=&quot;php_var&quot;&gt;$mso&lt;/span&gt; = &lt;span class=&quot;php_var&quot;&gt;$mySoapObjects&lt;/span&gt;[&lt;span class=&quot;php_red&quot;&gt;3&lt;/span&gt;];&lt;br /&gt; &lt;span class=&quot;php_var&quot;&gt;$mso&lt;/span&gt;[&lt;span class=&quot;php_string&quot;&gt;&#39;Name&#39;&lt;/span&gt;] = &lt;span class=&quot;php_string&quot;&gt;&quot;|||&quot;&lt;/span&gt;;&lt;br /&gt; &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;php_var&quot;&gt;$mso&lt;/span&gt;;&lt;br /&gt;}&lt;/pre&gt; The SOAP server registration: &lt;pre class=&quot;code&quot;&gt;&lt;span class=&quot;php_var&quot;&gt;$server&lt;/span&gt;-&gt;register(&lt;br /&gt;   &lt;span class=&quot;php_string&quot;&gt;&#39;ProcessMySoapObject&#39;&lt;/span&gt;,&lt;br /&gt;   &lt;span class=&quot;keyword&quot;&gt;array&lt;/span&gt;(&lt;span class=&quot;php_string&quot;&gt;&#39;soapObjects&#39;&lt;/span&gt;=&gt;&lt;span class=&quot;php_string&quot;&gt;&#39;tns:MySoapObjectArray&#39;&lt;/span&gt;),&lt;br /&gt;   &lt;span class=&quot;keyword&quot;&gt;array&lt;/span&gt;(&lt;span class=&quot;php_string&quot;&gt;&#39;return&#39;&lt;/span&gt;=&gt;&lt;span class=&quot;php_string&quot;&gt;&#39;tns:MySoapObject&#39;&lt;/span&gt;),&lt;br /&gt;   &lt;span class=&quot;php_var&quot;&gt;$ns&lt;/span&gt;,&lt;br /&gt;   &lt;span class=&quot;keyword&quot;&gt;false&lt;/span&gt;,&lt;br /&gt;   &lt;span class=&quot;php_string&quot;&gt;&#39;rpc&#39;&lt;/span&gt;,&lt;br /&gt;   &lt;span class=&quot;keyword&quot;&gt;false&lt;/span&gt;,&lt;br /&gt;   &lt;span class=&quot;php_string&quot;&gt;&#39;Processes an array of MySoapObjects and returns one of them&#39;&lt;/span&gt;);&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;And I did exactly the same as I did before--and added the web reference in visual studio to my project. This time not only did Visual Studio add the Service class and web method, it added the 2 data types I had defined in PHP on my SOAP server (actually, it just built the MySoapObject, and the array was left out because arrays are an implied data type).&lt;br /&gt;&lt;br /&gt;&lt;div class=&quot;big_image&quot;&gt;&lt;img nicetitle=&quot;The object browser showing the structure of the MySoapObject&quot; src=&quot;http://www.sanity-free.org/images/mysoap.gif&quot; border=&quot;0&quot; /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class=&quot;big_image&quot;&gt;&lt;img nicetitle=&quot;The object browser showing the method ProcessMySoapObject&quot; src=&quot;http://www.sanity-free.org/images/processmysoap.gif&quot; border=&quot;0&quot; /&gt;&lt;/div&gt;&lt;br /&gt;I changed my button click event in my windows form and added the following code: &lt;pre class=&quot;code&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;private void&lt;/span&gt; button1_Click(&lt;span class=&quot;keyword&quot;&gt;object&lt;/span&gt; sender, &lt;span class=&quot;class_def&quot;&gt;EventArgs&lt;/span&gt; e) {&lt;br /&gt;   &lt;span class=&quot;class_def&quot;&gt;Services&lt;/span&gt; s = &lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;class_def&quot;&gt;Services&lt;/span&gt;();&lt;br /&gt;   &lt;span class=&quot;class_def&quot;&gt;MySoapObject&lt;/span&gt;[] ms = &lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;class_def&quot;&gt;MySoapObject&lt;/span&gt;[10];&lt;br /&gt;   &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt;(&lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; i = 0; i &lt; ms.Length; i++) {&lt;br /&gt;       ms[i] = &lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;class_def&quot;&gt;MySoapObject&lt;/span&gt;();&lt;br /&gt;       ms[i].Author = &lt;span class=&quot;string&quot;&gt;&quot;Steve&quot;&lt;/span&gt;;&lt;br /&gt;       ms[i].Description = &lt;span class=&quot;string&quot;&gt;&quot;The One that should be returned&quot;&lt;/span&gt;;&lt;br /&gt;       ms[i].Name = i.ToString();&lt;br /&gt;       ms[i].Text = &lt;span class=&quot;string&quot;&gt;&quot;something something something &quot;&lt;/span&gt; + i.ToString();&lt;br /&gt;       ms[i].VoteCount = i * 2;&lt;br /&gt;       ms[i].VoteTotal = (&lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt;)&lt;span class=&quot;class_def&quot;&gt;Math&lt;/span&gt;.Pow(ms[i].VoteCount, 2);&lt;br /&gt;   }&lt;br /&gt;   &lt;span class=&quot;class_def&quot;&gt;MySoapObject&lt;/span&gt; retn = s.ProcessMySoapObject(ms);&lt;br /&gt;   &lt;span class=&quot;keyword&quot;&gt;string&lt;/span&gt; output = &lt;span class=&quot;string&quot;&gt;&quot;&quot;&lt;/span&gt;;&lt;br /&gt;   output += retn.Author + &lt;span class=&quot;string&quot;&gt;&quot;\t\t\r\n&quot;&lt;/span&gt;;&lt;br /&gt;   output += retn.Description + &lt;span class=&quot;string&quot;&gt;&quot;\t\t\r\n&quot;&lt;/span&gt;;&lt;br /&gt;   output += retn.Name + &lt;span class=&quot;string&quot;&gt;&quot;\t\t\r\n&quot;&lt;/span&gt;;&lt;br /&gt;   output += retn.Text + &lt;span class=&quot;string&quot;&gt;&quot;\t\t\r\n&quot;&lt;/span&gt;;&lt;br /&gt;   output += retn.VoteCount.ToString() + &lt;span class=&quot;string&quot;&gt;&quot;\t\t\r\n&quot;&lt;/span&gt;;&lt;br /&gt;   output += retn.VoteTotal.ToString() + &lt;span class=&quot;string&quot;&gt;&quot;\t\t\r\n&quot;&lt;/span&gt;;&lt;br /&gt;   &lt;span class=&quot;class_def&quot;&gt;MessageBox&lt;/span&gt;.Show(output);&lt;br /&gt;}&lt;/pre&gt; Compiled, ran and clicked.&lt;br /&gt;&lt;br /&gt;&lt;div class=&quot;big_image&quot;&gt;&lt;img nicetitle=&quot;The image of the message box that was returned when I clicked the button.&quot; src=&quot;http://www.sanity-free.org/images/mysoapdiagresults.gif&quot; border=&quot;0&quot; /&gt;&lt;/div&gt;&lt;br /&gt;Simple, Easy, Can&#39;t believe I never tried it before now!&lt;br /&gt;&lt;br /&gt;This opened up a whole new world of opportunities in cross-platform distributed computing that I&#39;d never exposed myself to before... what a wonderful thing!&lt;div class=&quot;blogger-post-footer&quot;&gt;octopus east java baker&lt;/div&gt;</description><link>http://scriptster.blogspot.com/2007/12/php-webservices-and-c-net-soap-clients.html</link><author>noreply@blogger.com (Octopus)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-2977499297091575918.post-5464474320836772998</guid><pubDate>Thu, 29 Nov 2007 07:57:00 +0000</pubDate><atom:updated>2007-11-28T23:59:27.689-08:00</atom:updated><title>The Future of PHP</title><description>&lt;a href=&quot;http://blog.panmedia.com.jm/blog/3&quot;&gt;source : Marc&#39;s blog&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Marc says :&lt;br /&gt;&lt;a href=&quot;http://blog.panmedia.com.jm/future-php&quot; title=&quot;The Future of PHP&quot;&gt;&lt;/a&gt;   &lt;div class=&quot;blogContent&quot;&gt;     &lt;p&gt;Last Friday there was a rather spirited discussion at the office between Kaiton (a Ruby aficionado and ex-Panmedia employee currently at Microsoft), Nesta (a python aficionado who is forced to use PHP) and myself, (an un-biased PHP user who is forced to defend it ;-). The topic of course was PHP, its woes, its past, its present and its future. &lt;/p&gt;  &lt;p&gt;According to Kaiton, PHP will be marginalised in 2008 by more literate programming languages like &lt;a href=&quot;http://www.ruby-lang.org/en/&quot;&gt;Ruby&lt;/a&gt;, &lt;a href=&quot;http://www.python.org/&quot;&gt;Python&lt;/a&gt; and even &lt;a href=&quot;http://www.erlang.org/&quot;&gt;Erlang&lt;/a&gt;. His view is that as the web becomes more important to business, backend programmers will start to get involved in the front end and web programming will be dominated by more experienced programmers who care more about the language they code with. According to Nesta, &lt;a href=&quot;http://drupal.org/&quot;&gt;Drupal&lt;/a&gt; is the only good thing that ever came out of PHP.  I think that 2007 will be the year of PHP.&lt;/p&gt;  &lt;p&gt;By the end of the &lt;del&gt;argument&lt;/del&gt; discussion, things were kinda starting to go around in circles so I decided to try and articulate my ideas in written format so that they could be dated, critiqued and openly ridiculed, and so that a year or two from now I can come back read the crazy things I was thinking way back in 2007. It will also serve as an official record in case Kaiton wants to put his money where his mouth is ;-)&lt;/p&gt;  &lt;p&gt;Before I present my argument, let me get a few things straight.  &lt;/p&gt;  &lt;p&gt;There are definitely &lt;strong&gt;some dislikeable things about PHP&lt;/strong&gt;. The language design (or lack thereof) is far from perfect. PHP’s roots and a laissez-faire approach to adding new features early on have scarred the language with inconsistent naming conventions and function behaviour. A late start in the object oriented game meant that it took them a little while to get that feature right. Its popularity has been its Achilles heel and prevented the developers from making radical sweeping changes to normalize the language.&lt;/p&gt;  &lt;p&gt;On the flip side there are &lt;strong&gt;a few unfair assertions that people tend to make against PHP&lt;/strong&gt;. I often hear people say &lt;em&gt;“you can’t build large apps in PHP, it just gets messy!”&lt;/em&gt;. While there is a lot of bad PHP code out there, that doesn’t mean you can’t write clean code. The PHP language does not enforce a lot rules to prevent you from coding sloppily; whether or not a language should police coders is a separate matter of debate. The fact remains however that PHP provides you with everything you need to code your applications according to tried and true &lt;a href=&quot;http://www.amazon.com/PHP-5-Objects-Patterns-Practice/dp/1590593804/&quot;&gt;Object Oriented Design Patterns&lt;/a&gt;.  Whether or not you choose to do so is up to you.&lt;/p&gt;  &lt;p&gt;Just so it is clear, I am not saying that PHP &lt;strong&gt;deserves&lt;/strong&gt; to prosper, I am not saying that I &lt;strong&gt;personally want it&lt;/strong&gt; to prosper, I am simply saying that &lt;strong&gt;it will prosper&lt;/strong&gt;. Here is why:&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;PHP is popular.  This has a couple ramifications.&lt;/strong&gt;&lt;/p&gt;  &lt;ul&gt;&lt;li&gt;&lt;p&gt;PHP 4 is available by default in just about any web-hosting plan you come across. And PHP 5 availability is rising steadily.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;It has been widely and heavily tested against a multitude of different environments and configurations (Hardware, OS, Database, 3rd party software, etc).&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;You are much more likely to have somebody in-house who knows at lease some PHP than &lt;strong&gt;any&lt;/strong&gt; Ruby or Python, and it is also much easier to hire a PHP developer.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;  &lt;p&gt;&lt;strong&gt;PHP 5 is “good enough”.&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Regardless of what you want to say about PHP’s language design (or complete lack thereof) as it currently stands at version 5.2:&lt;/p&gt;  &lt;ul&gt;&lt;li&gt;&lt;p&gt;It has sufficient object oriented features for coding according to enterprise patterns.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;It has deprecated the magic functions (register globals, magic quotes, etc) that have been the source of many security issues in the past an scheduled them for complete removal in PHP 6.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;The Internet’s &lt;a href=&quot;http://www.yahoo.com/&quot;&gt;most trafficked site&lt;/a&gt; is built using PHP.  They are heavily invested its success and are one of the major driving forces behind the PHP 6’s upcoming &lt;a href=&quot;http://devzone.zend.com/node/view/id/874&quot;&gt;Unicode support&lt;/a&gt;. They have a presentation online explaining &lt;a href=&quot;http://www.radwin.org/michael/blog/2005/10/php_at_yahoo_presentation_.html&quot;&gt;their rationale&lt;/a&gt; for choosing PHP.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;  &lt;p&gt;This meets my definition of good enough. Far from perfect, not necessarily the best, but good enough for web work of all sizes. &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;The PHP Collaboration Project makes PHP better.&lt;/strong&gt;&lt;/p&gt;  &lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;a href=&quot;http://framework.zend.com/&quot;&gt;The Zend Framework&lt;/a&gt; leads by example to help solve the sloppy PHP coder epidemic and give developers a solid basis for rapid application development.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a href=&quot;http://devzone.zend.com/&quot;&gt;The Zend Developer Zone&lt;/a&gt; plays in important role by engaging the community and providing example code. &lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;However, to me, the most important part of the Collaboration project is the &lt;a href=&quot;http://www.eclipse.org/php/&quot;&gt;new Eclipse based IDE/Debugger&lt;/a&gt;. A well designed, fully integrated free and open source graphical coding/debugging solution for PHP will a major step forward for web application development. One year from now many of use will scratch our heads in amazement at the primitive methods we used to employ for debugging complex web apps. The difference will be as huge as the jump from debugging JavaScript using alert messages to using Firebug 1.0 (more on that in a later blog post).&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;  &lt;p&gt;&lt;strong&gt;Zend knows how to compete&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;From a developer point of view the entire &lt;a href=&quot;http://www.zend.com/php_collaboration_project&quot;&gt;PHP Collaboration Project&lt;/a&gt; is an attempt to compete with ASP.NET. The combination of a Developer Zone, an IDE and a Framework are straight out of the Microsoft playbook. They are even working &lt;strong&gt;with&lt;/strong&gt; Microsoft to compete in the arena where Microsoft typically dominates… distribution to the windows desktop.  &lt;a href=&quot;http://www.zend.com/products/zend_core/windows_preview&quot;&gt;Zend Core for Windows&lt;/a&gt; will be a simple download and install and I wouldn’t put it past them to bundle the framework in as well.&lt;/p&gt;  &lt;p&gt;On the Framework level the Zend Framework competes with &lt;a href=&quot;http://www.rubyonrails.org/&quot;&gt;Ruby on Rails&lt;/a&gt;, &lt;a href=&quot;http://www.djangoproject.com/&quot;&gt;Django&lt;/a&gt; and &lt;a href=&quot;http://www.asp.net/&quot;&gt;ASP.Net&lt;/a&gt;.  It covers all the typical bases MVC, ORM, Caching, JSON, etc.&lt;/p&gt;  &lt;p&gt;On the language level PHP 5’s object-oriented improvements and PHP 6’s upcoming Unicode support give the language some more “enterprise” features, but I don’t think Zend is actually trying to compete with Java. Zend and Sun’s collaborated on &lt;a href=&quot;http://jcp.org/en/jsr/detail?id=223&quot;&gt;JSR-223&lt;/a&gt; (Scripting for the Java Platform) which will allow scripting languages like PHP to access Java objects in the recently released Java 6 JRE. When you combine this with the Java language support in Zend Studio 5.5 it indicates to me that Zend wants to co-exist rather than compete with Java.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Zend is making inroads into the corporate world&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Separate and apart from working with IBM, Intel, EBay and Amazon on the collaboration project, Zend has established partnerships with the major proprietary Database vendors and created a special set of PHP distributions just for them called Zend Core; this now includes &lt;a href=&quot;http://www.zend.com/products/zend_core/zend_core_for_oracle&quot;&gt;Zend Core for Oracle&lt;/a&gt;, and &lt;a href=&quot;http://www.zend.com/products/zend_core/zend_core_for_ibm&quot;&gt;Zend Core for IBM&lt;/a&gt; . Not only do these types of partnerships make companies feel more comfortable using PHP with the proprietary databases they have built their business on but they also offer a number of other benefits:&lt;/p&gt;  &lt;ul&gt;&lt;li&gt;&lt;p&gt;Improved drivers. By working directly with the database vendors, Zend has already made numerous improvements to the PHP extensions for Oracle and DB2.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Simplified distribution and setup for those who need to use proprietary drivers (since they aren’t distributed with the standard php.net download).&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;GUI based management. Each Zend Core distribution comes with a web based interface for viewing the server status and managing the PHP configuration. Zend Core also comes with an updater that allows you to easily apply and rollback PHP updates.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Zend Core provides a nice smooth &lt;a href=&quot;http://www.zend.com/products/zend_core/support&quot;&gt;on ramp to support&lt;/a&gt;. You can download the basic system for free and then choose your level of support later on. Support for PHP may not seem necessary to most developers but it is nice to have the option in case the company you are working for wants it.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;  &lt;p&gt;Not to be left behind, rumour has it that early this year we will see a &lt;a href=&quot;http://www.planetmysql.org/entries/4543&quot;&gt;Zend Core for MySQL&lt;/a&gt; as well as a brand &lt;a href=&quot;http://www.planetmysql.org/kaj/?p=69&quot;&gt;new MySQL driver&lt;/a&gt; developed specifically for PHP that provides added performance and reliability. When you consider this along with MySQL’s upcoming &lt;a href=&quot;http://mike.kruckenberg.com/archives/2006/04/jim_starkey_int.html&quot;&gt;Falcon&lt;/a&gt; &lt;a href=&quot;http://dev.mysql.com/doc/refman/5.1/en/se-falcon.html&quot;&gt;storage engine&lt;/a&gt; and their extremely useful &lt;a href=&quot;http://www.mysql.com/products/tools/&quot;&gt;GUI tools&lt;/a&gt;, 2007 may be the year of MySQL as well.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;The train has left the station&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;I have a python book here on my desk that is number 2 or 3 in my reading queue right now, I would really like to learn Ruby (but don’t see it happening anytime soon). I have no doubt that I will find both these languages more pleasant to code with than PHP, but my personal tastes have little to do with what I think will happen in 2007/2008. The PHP train is a rollin’ and my learning or loving another language ain’t gonna stop it.&lt;/p&gt;  &lt;p&gt;What do you think? Will 2007/2008 see PHP rise or fall?&lt;/p&gt;   &lt;/div&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;octopus east java baker&lt;/div&gt;</description><link>http://scriptster.blogspot.com/2007/11/future-of-php.html</link><author>noreply@blogger.com (Octopus)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-2977499297091575918.post-7153621035927735060</guid><pubDate>Thu, 29 Nov 2007 07:45:00 +0000</pubDate><atom:updated>2007-11-28T23:49:21.881-08:00</atom:updated><title>Zend Framework - Power PHP</title><description>&lt;div class=&quot;author_name&quot;&gt;         by          &lt;a href=&quot;http://www.bitwisemag.com/2/_Huw-Collingbourne_&quot;&gt;Huw Collingbourne&lt;/a&gt;          &lt;/div&gt;                                 &lt;div class=&quot;surtitre&quot;&gt;&lt;!-- debut_surligneconditionnel --&gt;Zend Interview...&lt;!-- finde_surligneconditionnel --&gt;&lt;/div&gt;&lt;!--end: cartouche / Title Block --&gt;      &lt;div style=&quot;line-height: 0em;&quot;&gt; &lt;/div&gt;&lt;!-- Bug Mozilla http://bugzilla.mozilla.org/show_bug.cgi?id=200510 --&gt;    &lt;!--optional elements...--&gt;       &lt;div class=&quot;chapo&quot;&gt;&lt;!-- debut_surligneconditionnel --&gt;&lt;div class=&quot;spip_document_153 spip_documents spip_documents_center&quot;&gt;  &lt;img src=&quot;http://www.bitwisemag.com/2/IMG/gif/zendframework.gif&quot; height=&quot;200&quot; width=&quot;500&quot; /&gt; &lt;/div&gt; &lt;p class=&quot;spip&quot;&gt;In July, Zend Technologies released version 1.0 of the Zend Framework, an open source application framework for PHP. Here, &lt;i class=&quot;spip&quot;&gt;Huw Collingbourne&lt;/i&gt; talks to &lt;i class=&quot;spip&quot;&gt;Mark de Visser&lt;/i&gt;, Zend’s Chief Marketing Officer, about Zend Framework, the future of PHP and the challenges of Ruby On Rails, Flex and Silverlight...&lt;/p&gt;&lt;!-- finde_surligneconditionnel --&gt;&lt;/div&gt;   &lt;!--intro/deck--&gt;       &lt;div class=&quot;texte&quot;&gt;&lt;!-- debut_surligneconditionnel --&gt;&lt;table class=&quot;spip&quot;&gt; &lt;tbody&gt; &lt;tr class=&quot;row_even&quot;&gt;&lt;td&gt; &lt;center&gt; &lt;strong class=&quot;spip&quot;&gt;So What Is ‘Zend Framework’, Anyhow...?&lt;/strong&gt; &lt;/center&gt; &lt;hr class=&quot;spip&quot;&gt; &lt;p class=&quot;spip&quot;&gt;&lt;i class=&quot;spip&quot;&gt;We asked Mark de Visser to give us an overview of the main features of the Zend Framework and what they offer to developers. This is what he told us...&lt;/i&gt;&lt;br /&gt;&lt;/p&gt;  &lt;hr class=&quot;spip&quot;&gt; &lt;p class=&quot;spip&quot;&gt;Zend Framework (ZF) is completely free for development and distribution, that is, is open-source and free to download &amp;amp; use and features the following:&lt;br /&gt;&lt;img src=&quot;http://www.bitwisemag.com/2/dist/puce.gif&quot; alt=&quot;-&quot; height=&quot;11&quot; width=&quot;8&quot; /&gt; New BSD license: business-friendly – it’s easy to build your own commercial intellectual property on top of ZF&lt;br /&gt;&lt;img src=&quot;http://www.bitwisemag.com/2/dist/puce.gif&quot; alt=&quot;-&quot; height=&quot;11&quot; width=&quot;8&quot; /&gt; An Apache-like Contributor License Agreement (CLA) process assures that the code is free of legal issues – important protection and peace-of-mind&lt;br /&gt;&lt;img src=&quot;http://www.bitwisemag.com/2/dist/puce.gif&quot; alt=&quot;-&quot; height=&quot;11&quot; width=&quot;8&quot; /&gt; Fully object-oriented PHP 5 class library, with attention to best design practices&lt;br /&gt;&lt;img src=&quot;http://www.bitwisemag.com/2/dist/puce.gif&quot; alt=&quot;-&quot; height=&quot;11&quot; width=&quot;8&quot; /&gt; Tested thoroughly with about 90,000 lines of test code for 140,000 lines of framework code, all contributors were asked to submit test code and documentation with every submission.&lt;br /&gt;&lt;img src=&quot;http://www.bitwisemag.com/2/dist/puce.gif&quot; alt=&quot;-&quot; height=&quot;11&quot; width=&quot;8&quot; /&gt; Extreme simplicity, modular “use-at-will” architecture for easy migration and ability to share ZF code with your current applications and even with other frameworks if necessary.&lt;br /&gt;That’s the high-level (above); more specific features and their benefits are here:&lt;br /&gt;&lt;br /&gt;&lt;img src=&quot;http://www.bitwisemag.com/2/dist/puce.gif&quot; alt=&quot;-&quot; height=&quot;11&quot; width=&quot;8&quot; /&gt; Model/View/Controller architecture – an industry standard best practice for web apps Full database support (incl. MySQL, PostgreSQL, SQLite, Oracle, DB2, &amp;amp; MS SQL Server) – all major databases you may need, with the ease-of-use you expect from a framework&lt;br /&gt;&lt;img src=&quot;http://www.bitwisemag.com/2/dist/puce.gif&quot; alt=&quot;-&quot; height=&quot;11&quot; width=&quot;8&quot; /&gt; Internationalization support necessary for most modern web applications – in a global economy providing localized versions in your users’ language is easy and straightforward&lt;br /&gt;&lt;img src=&quot;http://www.bitwisemag.com/2/dist/puce.gif&quot; alt=&quot;-&quot; height=&quot;11&quot; width=&quot;8&quot; /&gt; Authentication &amp;amp; sessions – to make managing sign-on &amp;amp; users of your application easy.&lt;br /&gt;&lt;img src=&quot;http://www.bitwisemag.com/2/dist/puce.gif&quot; alt=&quot;-&quot; height=&quot;11&quot; width=&quot;8&quot; /&gt; AJAX/JSON support – to help meet the ease-of-use your users now come to expect&lt;br /&gt;&lt;img src=&quot;http://www.bitwisemag.com/2/dist/puce.gif&quot; alt=&quot;-&quot; height=&quot;11&quot; width=&quot;8&quot; /&gt; Search – native PHP port of industry-standard Lucence search engine&lt;br /&gt;&lt;img src=&quot;http://www.bitwisemag.com/2/dist/puce.gif&quot; alt=&quot;-&quot; height=&quot;11&quot; width=&quot;8&quot; /&gt; Syndication (RSS &amp;amp; Atom supported) – don’t be left behind without the data formats &amp;amp; access your Web 2.0 users need&lt;br /&gt;&lt;img src=&quot;http://www.bitwisemag.com/2/dist/puce.gif&quot; alt=&quot;-&quot; height=&quot;11&quot; width=&quot;8&quot; /&gt; Web services – Zend Framework aims to be the premier place to consume and publish web services with support for REST, Http, Google Gdata APIs, Amazon, Flickr, Yahoo!, del.ici.ous, StrikeIron services, and others – create mashups and other web 2.0 apps easily.&lt;br /&gt;&lt;img src=&quot;http://www.bitwisemag.com/2/dist/puce.gif&quot; alt=&quot;-&quot; height=&quot;11&quot; width=&quot;8&quot; /&gt; Adobe PDF – support for PDF creation, reading, editing&lt;br /&gt;&lt;img src=&quot;http://www.bitwisemag.com/2/dist/puce.gif&quot; alt=&quot;-&quot; height=&quot;11&quot; width=&quot;8&quot; /&gt; Mail – read and send e-mail, including support for MIME Many other framework services including support for safer and more secure applications with input filtering, authentication, &amp;amp; HTML escaping, as well as caching, filtering, logging, input validation, and more.&lt;br /&gt;&lt;br /&gt;&lt;img src=&quot;http://www.bitwisemag.com/2/dist/puce.gif&quot; alt=&quot;-&quot; height=&quot;11&quot; width=&quot;8&quot; /&gt; Download Zend Framework: &lt;a href=&quot;http://framework.zend.com/&quot; class=&quot;spip_out&quot;&gt;http://framework.zend.com/&lt;/a&gt;&lt;/p&gt; &lt;/td&gt;&lt;/tr&gt; &lt;/tbody&gt; &lt;/table&gt; &lt;p class=&quot;spip&quot;&gt;&lt;strong class=&quot;spip&quot;&gt;HC:&lt;/strong&gt; &lt;i class=&quot;spip&quot;&gt;Let’s start by talking about the Zend Framework. There are already numerous PHP frameworks around - such as CakePHP, PEAR and CodeIgniter. Is the Zend Framework ‘in competition’ with those or can it be use in collaboration with them?&lt;/i&gt;&lt;/p&gt;  &lt;p class=&quot;spip&quot;&gt;&lt;strong class=&quot;spip&quot;&gt;Mark de Visser:&lt;/strong&gt; We would not say that Zend Framework competes per se, with any other PHP framework. Different frameworks have different aims and there really is no “one size fits all” in that regard.&lt;/p&gt;  &lt;p class=&quot;spip&quot;&gt;Due to its modular “use-at-will” architecture, Zend Framework can be used with any/all of these frameworks. As a result, bolting on the Lucene search engine, adding PDF generation/editing, or even re-architecting your app to be a modern model-view-controller web app can all be done to greater or lesser degrees, depending on which other framework you are working with.&lt;/p&gt;  &lt;p class=&quot;spip&quot;&gt;&lt;strong class=&quot;spip&quot;&gt;HC:&lt;/strong&gt; &lt;i class=&quot;spip&quot;&gt;What factors would determine which the choice of framework for a potential user? &lt;/i&gt;&lt;/p&gt;  &lt;p class=&quot;spip&quot;&gt;&lt;strong class=&quot;spip&quot;&gt;Mark de Visser:&lt;/strong&gt; We anticipate that larger enterprise developers will find Zend Framework an excellent choice to start any “green field” (new) project and that some of the factors they might use to choose a framework would be to carefully investigate: licensing (both of the framework itself and of any contributed code), how best practices are embodied in the framework, security support built-in, how thoroughly the code has been tested, how well it has been documented, how easy is it to migrate and whether or not you are ‘stuck’ in a particular way of doing things once migrated, as well as that it contains all the latest features one might want in a framework.&lt;/p&gt;  &lt;p class=&quot;spip&quot;&gt;&lt;strong class=&quot;spip&quot;&gt;HC:&lt;/strong&gt; &lt;i class=&quot;spip&quot;&gt;Recently CodeGear launched a ‘visual’ PHP system, Delphi For PHP, which has its own open source class library and a drag-and-drop application designer. Is this the way forward for PHP development? &lt;/i&gt;&lt;/p&gt;  &lt;p class=&quot;spip&quot;&gt;&lt;strong class=&quot;spip&quot;&gt;Mark de Visser:&lt;/strong&gt; We are not familiar with CodeGear’s approach but subscribe to the idea of enabling framework classes so they can be used in visual designers.&lt;/p&gt;  &lt;p class=&quot;spip&quot;&gt;&lt;strong class=&quot;spip&quot;&gt;HC:&lt;/strong&gt; &lt;i class=&quot;spip&quot;&gt;Over the past year or so, Ruby On Rails has emerged as an increasingly influential framework. If I were considering the pros and cons of developing a web application using Ruby On Rails or PHP and the Zend Framework, what things should I consider when coming to a decision? &lt;/i&gt;&lt;/p&gt;  &lt;p class=&quot;spip&quot;&gt;&lt;strong class=&quot;spip&quot;&gt;Mark de Visser:&lt;/strong&gt; We find that most programmers pick languages based on a number of criteria. We think that Zend Framework will be an important addition that makes PHP more attractive, just as Rails makes Ruby more attractive in others. .&lt;/p&gt;  &lt;p class=&quot;spip&quot;&gt;Aside from that, by choosing Ruby on Rails a developer subscribes to a whole approach, including semantics, naming conventions, application architecture, etc. In contrast, Zend Framework lets you use as much or as little of the framework as you wish, making it very easy to adopt it gradually for existing code bases.&lt;/p&gt;  &lt;p class=&quot;spip&quot;&gt;PHP is the technology used for many of the most scalable web applications, including Yahoo, Facebook and YouTube. These sites drive the decision for many commercial developers to PHP, and subsequently to Zend Framework.&lt;/p&gt;  &lt;p class=&quot;spip&quot;&gt;&lt;strong class=&quot;spip&quot;&gt;HC:&lt;/strong&gt; &lt;i class=&quot;spip&quot;&gt;One of the features of the Ruby language is that it is object oriented from the ground up. With PHP, objects have been ‘bolted onto’ the language, haven’t they? Doesn’t that mean that PHP won’t take advantage of things like, for example, rigorous encapsulation and data hiding? Isn’t that something that goes in Ruby’s favour?&lt;/i&gt;&lt;/p&gt;  &lt;p class=&quot;spip&quot;&gt;&lt;strong class=&quot;spip&quot;&gt;Mark de Visser:&lt;/strong&gt; A key part of the move from PHP 4 to 5 was to make objects first-class citizens, including rigorous encapsulation and data hiding. So with PHP5 programming in PHP is really no different than programming in any other object oriented languages.&lt;/p&gt;  &lt;p class=&quot;spip&quot;&gt;Zend Framework leverages this capability of PHP5 and to create a framework that is fully OO and rigorously encapsulates and hides data. By embodying object-oriented best practices Zend Framework helps a developer learn, and stay safe.&lt;/p&gt;  &lt;p class=&quot;spip&quot;&gt;&lt;strong class=&quot;spip&quot;&gt;HC:&lt;/strong&gt; &lt;i class=&quot;spip&quot;&gt;Can you explain what part Zend plays in the development of the PHP language? Do you have full control over the design and implementation? Or is the future of PHP determined by the efforts of the open source community?&lt;/i&gt;&lt;/p&gt;  &lt;p class=&quot;spip&quot;&gt;&lt;strong class=&quot;spip&quot;&gt;Mark de Visser:&lt;/strong&gt; Zend does not have control over PHP, although some of its employees are active participants in the decisions of the open source community. Zend benefits greatly from the vibrant PHP ecosystem and tries to give back to this community whenever possible. It has many of the developers who work on maintenance and future versions of PHP on its payroll and also supports major open source projects like Zend Framework and the Eclipse PHP Development Tools (PDT).&lt;/p&gt;  &lt;p class=&quot;spip&quot;&gt;&lt;strong class=&quot;spip&quot;&gt;HC:&lt;/strong&gt; &lt;i class=&quot;spip&quot;&gt;What is the state of development on PHP 6? What are the significant new features that will be added to the language and will they ‘break’ existing applications?&lt;/i&gt;&lt;/p&gt;  &lt;p class=&quot;spip&quot;&gt;&lt;strong class=&quot;spip&quot;&gt;Mark de Visser:&lt;/strong&gt; There is an active PHP open-source community at work on PHP 6. i18n with full unicode support for multi-byte characters and most likely namespaces seem to be the major features under consideration for PHP6.&lt;/p&gt;  &lt;p class=&quot;spip&quot;&gt;&lt;strong class=&quot;spip&quot;&gt;HC:&lt;/strong&gt; &lt;i class=&quot;spip&quot;&gt;There is a great deal of activity in the realm of so-called ‘Rich Internet Applications’ at the moment - a field currently dominated by Adobe’s Flex but now being challenged by Microsoft’s Silverlight. One of the special features of Silverlight is that it will be programmable using Python, VB, Ruby or JavaScript. Are Flex and Silverlight going to squeeze out PHP? Can PHP find a way of working with them?&lt;/i&gt;&lt;/p&gt;  &lt;p class=&quot;spip&quot;&gt;&lt;strong class=&quot;spip&quot;&gt;Mark de Visser:&lt;/strong&gt; PHP being a server-side language works just fine with Silverlight &amp;amp; Flex. Flex and PHP work together beautifully. There is an article on the Zend Developer Zone &lt;a href=&quot;http://devzone.zend.com/article/11-Integrating-Adobe-Flex-and-PHP&quot; class=&quot;spip_out&quot;&gt;HERE&lt;/a&gt; that explains this well - and is written by an Adobe employee. Additionally, Microsoft (one of our partners) has released an Atlas-based Ajax toolkit for PHP (some links you might see are on &lt;a href=&quot;http://ajax.asp.net/&quot; class=&quot;spip_out&quot;&gt;the main library site that Microsoft supports&lt;/a&gt;; also see &lt;a href=&quot;http://weblogs.asp.net/scottgu/archive/2006/09/11/_2200_Atlas_2200_-1.0-Naming-and-Roadmap.aspx&quot; class=&quot;spip_out&quot;&gt;HERE&lt;/a&gt;, &lt;a href=&quot;http://www.shankun.com/Atlas_Php_2.aspx&quot; class=&quot;spip_out&quot;&gt;HERE&lt;/a&gt; and &lt;a href=&quot;http://www.codeplex.com/phpmsajax&quot; class=&quot;spip_out&quot;&gt;HERE&lt;/a&gt;, which further strengthens the usage of PHP and other client-side technologies like Silverlight and Flex/Flash.&lt;/p&gt;  &lt;p class=&quot;spip&quot;&gt;Unrelated to those two, but a connector between client &amp;amp; server side is the WebORB project that you can find &lt;a href=&quot;http://www.themidnightcoders.com/&quot; class=&quot;spip_out&quot;&gt;HERE&lt;/a&gt;; they are also interested in building their code into Zend Framework—and they already have a free open-source PHP kit available now.&lt;/p&gt;  &lt;p class=&quot;spip&quot;&gt;&lt;strong class=&quot;spip&quot;&gt;HC:&lt;/strong&gt; &lt;i class=&quot;spip&quot;&gt;Finally, PHP has been one of the driving forces of ‘Web 2’. Looking ahead, five or ten years from now, how will the face of the web have changed and what part will PHP play in that?&lt;/i&gt;&lt;/p&gt;  &lt;p class=&quot;spip&quot;&gt;&lt;strong class=&quot;spip&quot;&gt;Mark de Visser:&lt;/strong&gt; Zend finds predictions of that sort difficult at best. But as Andi Gutmans, Zend CTO for Product Strategy and co-founder has said in a recent &lt;a href=&quot;http://www.computerworld.com/action/article.do?command=viewArticleTOC&amp;amp;articleId=9023123&quot; class=&quot;spip_out&quot;&gt;ComputerWorld profile&lt;/a&gt;  of him:&lt;/p&gt;  &lt;blockquote class=&quot;spip&quot;&gt; &lt;p class=&quot;spip&quot;&gt;“One trend that I think is going to be critical to the IT industry in the coming years is the decentralization of IT. It is being enabled by a few factors. The first is dynamic languages like PHP, which are making it increasingly easy for lightweight developers to become productive. The second is the rise of service-oriented architecture, which is leading to the end of monolithic application architectures. Third, the shift toward Web applications that are making it extremely easy to deploy applications inside the enterprise, not requiring a central function to test, deploy and manage those applications. This change is going to allow companies to become far more productive and agile, significantly decreasing the traditional backlog of business applications IT has in its queue. It will also enable an increasing number of such applications to leverage the organization’s existing assets by integrating the SOA-enabled infrastructure.”&lt;/p&gt; &lt;/blockquote&gt; &lt;p class=&quot;spip&quot;&gt;As a follow-up to Andi’s prognostications we’ll also mention that IBM has built a management dashboard ‘mash-up’ tool of sorts to do just that, that is, leverage an organization’s existing assets—and though it’s just getting released, it’s already a fairly high profile project at IBM gaining them many SOA-enabled customers—and is called QEDWiki (Quickly &amp;amp; Easily Done Wiki) which is built entirely on Zend Framework. You can find out more about this project here: &lt;a href=&quot;http://services.alphaworks.ibm.com/qedwiki/&quot; class=&quot;spip_out&quot;&gt;http://services.alphaworks.ibm.com/qedwiki/&lt;/a&gt;&lt;/p&gt;  &lt;p class=&quot;spip&quot;&gt;You also may want to view this demo here: &lt;a href=&quot;http://www.alphaworks.ibm.com/demo/flash/display/qedwiki4&quot; class=&quot;spip_out&quot;&gt;http://www.alphaworks.ibm.com/demo/flash/display/qedwiki4&lt;/a&gt;&lt;/p&gt;  &lt;hr class=&quot;spip&quot;&gt; &lt;p class=&quot;spip&quot;&gt;&lt;strong class=&quot;spip&quot;&gt;Zend Technologies, Inc.&lt;/strong&gt;, the PHP company (&lt;a href=&quot;http://www.zend.com/&quot; class=&quot;spip_out&quot;&gt;http://www.zend.com/&lt;/a&gt;), is the leading provider of products and services for developing, deploying and managing business-critical PHP applications. Zend’s founders are the architects of PHP, which is used by more than 22 million Web sites.&lt;/p&gt;  &lt;p class=&quot;spip&quot;&gt;&lt;strong class=&quot;spip&quot;&gt;Mark de Visser&lt;/strong&gt; joined Zend in December 2005. Previously he worked for Agitar Software, a supplier of tools for Java software developers. Before Agitar, de Visser was vice president of marketing at Red Hat Inc. where he was a member of the team that created the company’s market-leading position with the introduction of Red Hat Enterprise Linux. He also worked for twelve years at Borland International in international and product marketing roles, and as vice president of corporate marketing.&lt;/p&gt;&lt;/div&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;octopus east java baker&lt;/div&gt;</description><link>http://scriptster.blogspot.com/2007/11/zend-framework-power-php.html</link><author>noreply@blogger.com (Octopus)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-2977499297091575918.post-7992923372768308599</guid><pubDate>Wed, 21 Nov 2007 08:10:00 +0000</pubDate><atom:updated>2007-11-21T00:11:48.154-08:00</atom:updated><title>Caching in PHP using the filesystem, APC and Memcached</title><description>By Evert on 2006-11-01 02:14:18&lt;br /&gt;&lt;p&gt;Caching is very important and really pays off in big internet applications. When you cache the data you&#39;re fetching from the database, in a lot of cases the load on your servers can be reduced enormously. &lt;/p&gt;&lt;br /&gt;&lt;p&gt;One way of caching, is simply storing the results of your database queries in files.. Opening a file and unserializing is often a lot faster than doing an expensive SELECT query with multiple joins. &lt;/p&gt;&lt;br /&gt;&lt;p&gt;Here&#39;s a simple file-based caching engine. &lt;/p&gt;&lt;br /&gt;&amp;lt;?php &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;//&amp;nbsp;Our&amp;nbsp;class &lt;br&gt;&lt;br /&gt;class&amp;nbsp; FileCache&amp;nbsp; { &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;//&amp;nbsp;This&amp;nbsp;is&amp;nbsp;the&amp;nbsp;function&amp;nbsp;you&amp;nbsp;store&amp;nbsp;information&amp;nbsp;with &lt;br&gt;&lt;br /&gt;function&amp;nbsp; store ( $key , $data , $ttl )&amp;nbsp;{ &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;//&amp;nbsp;Opening&amp;nbsp;the&amp;nbsp;file &lt;br&gt;&lt;br /&gt;$h&amp;nbsp; =&amp;nbsp; fopen ( $this -&amp;gt; getFileName ( $key ), &#39;w&#39; ); &lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if&amp;nbsp;(! $h )&amp;nbsp;throw&amp;nbsp;new&amp;nbsp; Exception ( &#39;Could&amp;nbsp;not&amp;nbsp;write&amp;nbsp;to&amp;nbsp;cache&#39; ); &lt;br&gt;&lt;br /&gt;//&amp;nbsp;Serializing&amp;nbsp;along&amp;nbsp;with&amp;nbsp;the&amp;nbsp;TTL &lt;br&gt;&lt;br /&gt;$data&amp;nbsp; =&amp;nbsp; serialize (array( time ()+ $ttl , $data )); &lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if&amp;nbsp;( fwrite ( $h , $data )=== false )&amp;nbsp;{ &lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; throw&amp;nbsp;new&amp;nbsp; Exception ( &#39;Could&amp;nbsp;not&amp;nbsp;write&amp;nbsp;to&amp;nbsp;cache&#39; ); &lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br&gt;&lt;br /&gt;fclose ( $h ); &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; } &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;//&amp;nbsp;General&amp;nbsp;function&amp;nbsp;to&amp;nbsp;find&amp;nbsp;the&amp;nbsp;filename&amp;nbsp;for&amp;nbsp;a&amp;nbsp;certain&amp;nbsp;key &lt;br&gt;&lt;br /&gt;private&amp;nbsp;function&amp;nbsp; getFileName ( $key )&amp;nbsp;{ &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return&amp;nbsp; &#39;/tmp/s_cache&#39;&amp;nbsp; .&amp;nbsp; md5 ( $key ); &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; } &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;//&amp;nbsp;The&amp;nbsp;function&amp;nbsp;to&amp;nbsp;fetch&amp;nbsp;data&amp;nbsp;returns&amp;nbsp;false&amp;nbsp;on&amp;nbsp;failure &lt;br&gt;&lt;br /&gt;function&amp;nbsp; fetch ( $key )&amp;nbsp;{ &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;$filename&amp;nbsp; =&amp;nbsp; $this -&amp;gt; getFileName ( $key ); &lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if&amp;nbsp;(! file_exists ( $filename )&amp;nbsp;||&amp;nbsp;! is_readable ( $filename ))&amp;nbsp;return&amp;nbsp; false ; &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;$data&amp;nbsp; =&amp;nbsp; file_get_contents ( $filename ); &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;$data&amp;nbsp; =&amp;nbsp;@ unserialize ( $data ); &lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if&amp;nbsp;(! $data )&amp;nbsp;{ &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;//&amp;nbsp;Unlinking&amp;nbsp;the&amp;nbsp;file&amp;nbsp;when&amp;nbsp;unserializing&amp;nbsp;failed &lt;br&gt;&lt;br /&gt;unlink ( $filename ); &lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return&amp;nbsp; false ; &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;//&amp;nbsp;checking&amp;nbsp;if&amp;nbsp;the&amp;nbsp;data&amp;nbsp;was&amp;nbsp;expired &lt;br&gt;&lt;br /&gt;if&amp;nbsp;( time ()&amp;nbsp;&amp;gt;&amp;nbsp; $data [ 0 ])&amp;nbsp;{ &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;//&amp;nbsp;Unlinking &lt;br&gt;&lt;br /&gt;unlink ( $filename ); &lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return&amp;nbsp; false ; &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return&amp;nbsp; $data [ 1 ]; &lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;} &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;?&amp;gt;&lt;br /&gt;&lt;h3&gt;Key strategies &lt;/h3&gt;&lt;br /&gt;&lt;p&gt;All the data is identified by a key. Your keys have to be unique system wide; it is therefore a good idea to namespace your keys. My personal preference is to name the key by the class thats storing the data, combined with for example an id. &lt;/p&gt;&lt;br /&gt;&lt;h4&gt;example &lt;/h4&gt;&lt;br /&gt;&lt;p&gt;Your user-management class is called My_Auth, and all users are identified by an id. A sample key for cached user-data would then be &quot; &lt;em&gt;My_Auth:users:1234 &lt;/em&gt;&quot;. &#39;1234&#39; is here the user id. &lt;/p&gt;&lt;br /&gt;&lt;h4&gt;Some reasoning behind this code &lt;/h4&gt;&lt;br /&gt;&lt;p&gt;I chose 4096 bytes per chunk, because this is often the default inode size in linux and this or a multiple of this is generally the fastest. Much later I found out file_get_contents is actually faster. &lt;/p&gt;&lt;br /&gt;&lt;p&gt;Lots of caching engines based on files actually don&#39;t specify the TTL (the time it takes before the cache expires) at the time of storing data in the cache, but while fetching it from the cache. This has one big advantage; you can check if a file is valid before actually opening the file, using the last modified time ( &lt;a href=&quot;http://www.php.net/filemtime&quot;&gt;filemtime() &lt;/a&gt;). &lt;/p&gt;&lt;br /&gt;&lt;p&gt;The reason I did not go with this approach is because most non-file based cache systems do specify the TTL on storing the data, and as you will see later in the article we want to keep things compatible. Another advantage of storing the TTL in the data, is that we can create a cleanup script later that will delete expired cache files. &lt;/p&gt;&lt;br /&gt;&lt;h3&gt;Usage of this class &lt;/h3&gt;&lt;br /&gt;&lt;p&gt;The number one place in web applications where caching is a good idea is on database queries. MySQL and others usually have a built-in cache, but it is far from optimal, mainly because they have no awareness of the logic of you application (and they shouldn&#39;t have), and the cache is usually flushed whenever there&#39;s an update on a table. Here is a sample function that fetches user data and caches the result for 10 minutes. &lt;/p&gt;&lt;br /&gt;&amp;lt;?php &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;//&amp;nbsp;constructing&amp;nbsp;our&amp;nbsp;cache&amp;nbsp;engine &lt;br&gt;&lt;br /&gt;$cache&amp;nbsp; =&amp;nbsp;new&amp;nbsp; FileCache (); &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&amp;nbsp; function&amp;nbsp; getUsers ()&amp;nbsp;{ &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; global&amp;nbsp; $cache ; &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;//&amp;nbsp;A&amp;nbsp;somewhat&amp;nbsp;unique&amp;nbsp;key &lt;br&gt;&lt;br /&gt;$key&amp;nbsp; =&amp;nbsp; &#39;getUsers:selectAll&#39; ; &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;//&amp;nbsp;check&amp;nbsp;if&amp;nbsp;the&amp;nbsp;data&amp;nbsp;is&amp;nbsp;not&amp;nbsp;in&amp;nbsp;the&amp;nbsp;cache&amp;nbsp;already &lt;br&gt;&lt;br /&gt;if&amp;nbsp;(! $data&amp;nbsp; =&amp;nbsp; $cache -&amp;gt; fetch ( $key ))&amp;nbsp;{ &lt;br&gt;&lt;br /&gt;//&amp;nbsp;there&amp;nbsp;was&amp;nbsp;no&amp;nbsp;cache&amp;nbsp;version,&amp;nbsp;we&amp;nbsp;are&amp;nbsp;fetching&amp;nbsp;fresh&amp;nbsp;data &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //&amp;nbsp;assuming&amp;nbsp;there&amp;nbsp;is&amp;nbsp;a&amp;nbsp;database&amp;nbsp;connection &lt;br&gt;&lt;br /&gt;$result&amp;nbsp; =&amp;nbsp; mysql_query ( &quot;SELECT&amp;nbsp;*&amp;nbsp;FROM&amp;nbsp;users&quot; ); &lt;br&gt;&lt;br /&gt;$data&amp;nbsp; =&amp;nbsp;array(); &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;//&amp;nbsp;fetching&amp;nbsp;all&amp;nbsp;the&amp;nbsp;data&amp;nbsp;and&amp;nbsp;putting&amp;nbsp;it&amp;nbsp;in&amp;nbsp;an&amp;nbsp;array &lt;br&gt;&lt;br /&gt;while( $row&amp;nbsp; =&amp;nbsp; mysql_fetch_assoc ( $result ))&amp;nbsp;{&amp;nbsp; $data []&amp;nbsp;=&amp;nbsp; $row ;&amp;nbsp;} &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;//&amp;nbsp;Storing&amp;nbsp;the&amp;nbsp;data&amp;nbsp;in&amp;nbsp;the&amp;nbsp;cache&amp;nbsp;for&amp;nbsp;10&amp;nbsp;minutes &lt;br&gt;&lt;br /&gt;$cache -&amp;gt; store ( $key , $data , 600 ); &lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return&amp;nbsp; $data ; &lt;br&gt;&lt;br /&gt;} &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;$users&amp;nbsp; =&amp;nbsp; getUsers (); &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;?&amp;gt;&lt;br /&gt;&lt;p&gt;The reason i picked the mysql_ set of functions here, is because most of the readers will probably know these.. Personally I prefer PDO or another abstraction library. This example assumes there&#39;s a database connection, a users table and other issues. &lt;/p&gt;&lt;br /&gt;&lt;h3&gt;Problems with the library &lt;/h3&gt;&lt;br /&gt;&lt;p&gt;The first problem is simple, the library will only work on linux, because it uses the /tmp folder. Luckily we can use the php.ini setting &#39;session.save_path&#39;. &lt;/p&gt;&lt;br /&gt;&amp;lt;?php &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;private&amp;nbsp;function&amp;nbsp; getFileName ( $key )&amp;nbsp;{ &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return&amp;nbsp; ini_get ( &#39;session.save_path&#39; )&amp;nbsp;.&amp;nbsp; &#39;/s_cache&#39;&amp;nbsp; .&amp;nbsp; md5 ( $key ); &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; } &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;?&amp;gt;&lt;br /&gt;&lt;p&gt;The next problem is a little bit more complex. In the case where one of our cache files is being read, and in the same time being written by another process, you can get really unusual results. Caching bugs can be hard to find because they only occur in really specific circumstances, therefore you might never really see this issue happening yourself, somewhere out there your user will. &lt;/p&gt;&lt;br /&gt;&lt;p&gt;PHP can lock files with &lt;a href=&quot;http://www.php.net/flock&quot;&gt;flock() &lt;/a&gt;. Flock operates on an open file handle (opened by fopen) and either locks a file for reading (shared lock, everybody can read the file) or writing (exclusive lock, everybody waits till the writing is done and the lock is released). Because file_get_contents is the most efficient, and we can only use flock on filehandles, we&#39;ll use a combination of both. &lt;/p&gt;&lt;br /&gt;&lt;p&gt;The updated store and fetch methods will look like this &lt;/p&gt;&lt;br /&gt;&amp;lt;?php &lt;br&gt;&lt;br /&gt;//&amp;nbsp;This&amp;nbsp;is&amp;nbsp;the&amp;nbsp;function&amp;nbsp;you&amp;nbsp;store&amp;nbsp;information&amp;nbsp;with &lt;br&gt;&lt;br /&gt;function&amp;nbsp; store ( $key , $data , $ttl )&amp;nbsp;{ &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;//&amp;nbsp;Opening&amp;nbsp;the&amp;nbsp;file&amp;nbsp;in&amp;nbsp;read/write&amp;nbsp;mode &lt;br&gt;&lt;br /&gt;$h&amp;nbsp; =&amp;nbsp; fopen ( $this -&amp;gt; getFileName ( $key ), &#39;a+&#39; ); &lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if&amp;nbsp;(! $h )&amp;nbsp;throw&amp;nbsp;new&amp;nbsp; Exception ( &#39;Could&amp;nbsp;not&amp;nbsp;write&amp;nbsp;to&amp;nbsp;cache&#39; ); &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;flock ( $h , LOCK_EX );&amp;nbsp; //&amp;nbsp;exclusive&amp;nbsp;lock,&amp;nbsp;will&amp;nbsp;get&amp;nbsp;released&amp;nbsp;when&amp;nbsp;the&amp;nbsp;file&amp;nbsp;is&amp;nbsp;closed &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;fseek ( $h , 0 );&amp;nbsp; //&amp;nbsp;go&amp;nbsp;to&amp;nbsp;the&amp;nbsp;beginning&amp;nbsp;of&amp;nbsp;the&amp;nbsp;file &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //&amp;nbsp;truncate&amp;nbsp;the&amp;nbsp;file &lt;br&gt;&lt;br /&gt;ftruncate ( $h , 0 ); &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;//&amp;nbsp;Serializing&amp;nbsp;along&amp;nbsp;with&amp;nbsp;the&amp;nbsp;TTL &lt;br&gt;&lt;br /&gt;$data&amp;nbsp; =&amp;nbsp; serialize (array( time ()+ $ttl , $data )); &lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if&amp;nbsp;( fwrite ( $h , $data )=== false )&amp;nbsp;{ &lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; throw&amp;nbsp;new&amp;nbsp; Exception ( &#39;Could&amp;nbsp;not&amp;nbsp;write&amp;nbsp;to&amp;nbsp;cache&#39; ); &lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br&gt;&lt;br /&gt;fclose ( $h ); &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; } &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; function&amp;nbsp; fetch ( $key )&amp;nbsp;{ &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;$filename&amp;nbsp; =&amp;nbsp; $this -&amp;gt; getFileName ( $key ); &lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if&amp;nbsp;(! file_exists ( $filename ))&amp;nbsp;return&amp;nbsp; false ; &lt;br&gt;&lt;br /&gt;$h&amp;nbsp; =&amp;nbsp; fopen ( $filename , &#39;r&#39; ); &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if&amp;nbsp;(! $h )&amp;nbsp;return&amp;nbsp; false ; &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;//&amp;nbsp;Getting&amp;nbsp;a&amp;nbsp;shared&amp;nbsp;lock&amp;nbsp; &lt;br&gt;&lt;br /&gt;flock ( $h , LOCK_SH ); &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;$data&amp;nbsp; =&amp;nbsp; file_get_contents ( $filename ); &lt;br&gt;&lt;br /&gt;fclose ( $h ); &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;$data&amp;nbsp; =&amp;nbsp;@ unserialize ( $data ); &lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if&amp;nbsp;(! $data )&amp;nbsp;{ &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;//&amp;nbsp;If&amp;nbsp;unserializing&amp;nbsp;somehow&amp;nbsp;didn&#39;t&amp;nbsp;work&amp;nbsp;out,&amp;nbsp;we&#39;ll&amp;nbsp;delete&amp;nbsp;the&amp;nbsp;file &lt;br&gt;&lt;br /&gt;unlink ( $filename ); &lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return&amp;nbsp; false ; &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if&amp;nbsp;( time ()&amp;nbsp;&amp;gt;&amp;nbsp; $data [ 0 ])&amp;nbsp;{ &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;//&amp;nbsp;Unlinking&amp;nbsp;when&amp;nbsp;the&amp;nbsp;file&amp;nbsp;was&amp;nbsp;expired &lt;br&gt;&lt;br /&gt;unlink ( $filename ); &lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return&amp;nbsp; false ; &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return&amp;nbsp; $data [ 1 ]; &lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;?&amp;gt;&lt;br /&gt;&lt;p&gt;Well that actually wasn&#39;t too hard.. Only 3 new lines.. The next issue we&#39;re facing is updates of data. When somebody updates, say, a page in the cms; they usually expect the respecting page to update instantly.. In those cases you can update the data using store(), but in some cases it is simply more convenient to flush the cache.. So we need a delete method. &lt;/p&gt;&lt;br /&gt;&amp;lt;?php &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;function&amp;nbsp; delete (&amp;nbsp; $key&amp;nbsp; )&amp;nbsp;{ &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;$filename&amp;nbsp; =&amp;nbsp; $this -&amp;gt; getFileName ( $key ); &lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if&amp;nbsp;( file_exists ( $filename ))&amp;nbsp;{ &lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return&amp;nbsp; unlink ( $filename ); &lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&amp;nbsp;else&amp;nbsp;{ &lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return&amp;nbsp; false ; &lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;?&amp;gt;&lt;br /&gt;&lt;h3&gt;Abstracting the code &lt;/h3&gt;&lt;br /&gt;&lt;p&gt;This cache class is pretty straight-forward. The only methods in there are delete, store and fetch.. We can easily abstract that into the following base class. I&#39;m also giving it a proper prefix (I tend to prefix everything with Sabre, name yours whatever you want..). A good reason to prefix all your classes, is that they will never collide with other classnames if you need to include other code. The PEAR project made a stupid mistake by naming one of their classes &#39;Date&#39;, by doing this and refusing to change this they actually prevented an internal PHP-date class to be named Date. &lt;/p&gt;&lt;br /&gt;&amp;lt;?php &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;abstract&amp;nbsp;class&amp;nbsp; Sabre_Cache_Abstract&amp;nbsp; { &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; abstract&amp;nbsp;function&amp;nbsp; fetch ( $key ); &lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; abstract&amp;nbsp;function&amp;nbsp; store ( $key , $data , $ttl ); &lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; abstract&amp;nbsp;function&amp;nbsp; delete ( $key ); &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;?&amp;gt;&lt;br /&gt;&lt;p&gt;The resulting FileCache (which I&#39;l rename to Filesystem) is: &lt;/p&gt;&lt;br /&gt;&amp;lt;?php &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;class&amp;nbsp; Sabre_Cache_Filesystem&amp;nbsp; extends&amp;nbsp; Sabre_Cache_Abstract&amp;nbsp; { &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;//&amp;nbsp;This&amp;nbsp;is&amp;nbsp;the&amp;nbsp;function&amp;nbsp;you&amp;nbsp;store&amp;nbsp;information&amp;nbsp;with &lt;br&gt;&lt;br /&gt;function&amp;nbsp; store ( $key , $data , $ttl )&amp;nbsp;{ &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;//&amp;nbsp;Opening&amp;nbsp;the&amp;nbsp;file&amp;nbsp;in&amp;nbsp;read/write&amp;nbsp;mode &lt;br&gt;&lt;br /&gt;$h&amp;nbsp; =&amp;nbsp; fopen ( $this -&amp;gt; getFileName ( $key ), &#39;a+&#39; ); &lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if&amp;nbsp;(! $h )&amp;nbsp;throw&amp;nbsp;new&amp;nbsp; Exception ( &#39;Could&amp;nbsp;not&amp;nbsp;write&amp;nbsp;to&amp;nbsp;cache&#39; ); &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;flock ( $h , LOCK_EX );&amp;nbsp; //&amp;nbsp;exclusive&amp;nbsp;lock,&amp;nbsp;will&amp;nbsp;get&amp;nbsp;released&amp;nbsp;when&amp;nbsp;the&amp;nbsp;file&amp;nbsp;is&amp;nbsp;closed &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;fseek ( $h , 0 );&amp;nbsp; //&amp;nbsp;go&amp;nbsp;to&amp;nbsp;the&amp;nbsp;start&amp;nbsp;of&amp;nbsp;the&amp;nbsp;file &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //&amp;nbsp;truncate&amp;nbsp;the&amp;nbsp;file &lt;br&gt;&lt;br /&gt;ftruncate ( $h , 0 ); &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;//&amp;nbsp;Serializing&amp;nbsp;along&amp;nbsp;with&amp;nbsp;the&amp;nbsp;TTL &lt;br&gt;&lt;br /&gt;$data&amp;nbsp; =&amp;nbsp; serialize (array( time ()+ $ttl , $data )); &lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if&amp;nbsp;( fwrite ( $h , $data )=== false )&amp;nbsp;{ &lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; throw&amp;nbsp;new&amp;nbsp; Exception ( &#39;Could&amp;nbsp;not&amp;nbsp;write&amp;nbsp;to&amp;nbsp;cache&#39; ); &lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br&gt;&lt;br /&gt;fclose ( $h ); &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; } &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;//&amp;nbsp;The&amp;nbsp;function&amp;nbsp;to&amp;nbsp;fetch&amp;nbsp;data&amp;nbsp;returns&amp;nbsp;false&amp;nbsp;on&amp;nbsp;failure &lt;br&gt;&lt;br /&gt;function&amp;nbsp; fetch ( $key )&amp;nbsp;{ &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;$filename&amp;nbsp; =&amp;nbsp; $this -&amp;gt; getFileName ( $key ); &lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if&amp;nbsp;(! file_exists ( $filename ))&amp;nbsp;return&amp;nbsp; false ; &lt;br&gt;&lt;br /&gt;$h&amp;nbsp; =&amp;nbsp; fopen ( $filename , &#39;r&#39; ); &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if&amp;nbsp;(! $h )&amp;nbsp;return&amp;nbsp; false ; &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;//&amp;nbsp;Getting&amp;nbsp;a&amp;nbsp;shared&amp;nbsp;lock&amp;nbsp; &lt;br&gt;&lt;br /&gt;flock ( $h , LOCK_SH ); &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;$data&amp;nbsp; =&amp;nbsp; file_get_contents ( $filename ); &lt;br&gt;&lt;br /&gt;fclose ( $h ); &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;$data&amp;nbsp; =&amp;nbsp;@ unserialize ( $data ); &lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if&amp;nbsp;(! $data )&amp;nbsp;{ &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;//&amp;nbsp;If&amp;nbsp;unserializing&amp;nbsp;somehow&amp;nbsp;didn&#39;t&amp;nbsp;work&amp;nbsp;out,&amp;nbsp;we&#39;ll&amp;nbsp;delete&amp;nbsp;the&amp;nbsp;file &lt;br&gt;&lt;br /&gt;unlink ( $filename ); &lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return&amp;nbsp; false ; &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if&amp;nbsp;( time ()&amp;nbsp;&amp;gt;&amp;nbsp; $data [ 0 ])&amp;nbsp;{ &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;//&amp;nbsp;Unlinking&amp;nbsp;when&amp;nbsp;the&amp;nbsp;file&amp;nbsp;was&amp;nbsp;expired &lt;br&gt;&lt;br /&gt;unlink ( $filename ); &lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return&amp;nbsp; false ; &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return&amp;nbsp; $data [ 1 ]; &lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; function&amp;nbsp; delete (&amp;nbsp; $key&amp;nbsp; )&amp;nbsp;{ &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;$filename&amp;nbsp; =&amp;nbsp; $this -&amp;gt; getFileName ( $key ); &lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if&amp;nbsp;( file_exists ( $filename ))&amp;nbsp;{ &lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return&amp;nbsp; unlink ( $filename ); &lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&amp;nbsp;else&amp;nbsp;{ &lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return&amp;nbsp; false ; &lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; private&amp;nbsp;function&amp;nbsp; getFileName ( $key )&amp;nbsp;{ &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return&amp;nbsp; ini_get ( &#39;session.save_path&#39; )&amp;nbsp;.&amp;nbsp; &#39;/s_cache&#39;&amp;nbsp; .&amp;nbsp; md5 ( $key ); &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; } &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;} &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;?&amp;gt;&lt;br /&gt;&lt;p&gt;There you go, a complete, proper OOP, file-based caching class... I hope I explained things well. &lt;/p&gt;&lt;br /&gt;&lt;h3&gt;Memory based caching through APC &lt;/h3&gt;&lt;br /&gt;&lt;p&gt;If files aren&#39;t fast enough for you, and you have enough memory to spare.. Memory-based caching might be the solution. Obviously, storing and retrieving stuff from memory is a lot faster. The &lt;a href=&quot;http://pecl.php.net/package/APC&quot;&gt;APC &lt;/a&gt; extension not only does opcode cache (speeds up your php scripts by caching the parsed php script), but it also provides a simple mechanism to store data in shared memory. &lt;/p&gt;&lt;br /&gt;&lt;p&gt;Using shared memory in APC is extremely simple, I&#39;m not even going to explain it, the code should tell enough. &lt;/p&gt;&lt;br /&gt;&amp;lt;?php &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;class&amp;nbsp; Sabre_Cache_APC&amp;nbsp; extends&amp;nbsp; Sabre_Cache_Abstract&amp;nbsp; { &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; function&amp;nbsp; fetch ( $key )&amp;nbsp;{ &lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return&amp;nbsp; apc_fetch ( $key ); &lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; function&amp;nbsp; store ( $key , $data , $ttl )&amp;nbsp;{ &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return&amp;nbsp; apc_store ( $key , $data , $ttl ); &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; function&amp;nbsp; delete ( $key )&amp;nbsp;{ &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return&amp;nbsp; apc_delete ( $key ); &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;?&amp;gt;&lt;br /&gt;&lt;p&gt;My personal problem with APC that it tends to break my code.. So if you want to use it.. give it a testrun.. I have to admit that I haven&#39;t checked it anymore since they fixed &#39;my&#39; &lt;a href=&quot;http://pecl.php.net/bugs/bug.php?id=5314&quot;&gt;bug &lt;/a&gt;. . This bug is now fixed, APC is amazing for single-server applications and for the really often used data. &lt;/p&gt;&lt;br /&gt;&lt;h3&gt;Memcached &lt;/h3&gt;&lt;br /&gt;&lt;p&gt;Problems start when you are dealing with more than one webserver. Since there is no shared cache between the servers situations can occur where data is updated on one server and it takes a while before the other server is up to date.. It can be really useful to have a really high TTL on your data and simply replace or delete the cache whenever there is an actual update. When you are dealing with multiple webservers this scheme is simply not possible with the previous caching methods. &lt;/p&gt;&lt;br /&gt;&lt;p&gt;Introducing &lt;a href=&quot;http://www.danga.com/memcached/&quot;&gt;memcached &lt;/a&gt;. Memcached is a cache server originally developed by the LiveJournal people and now being used by sites like &lt;a href=&quot;http://digg.com/&quot;&gt;Digg &lt;/a&gt;, &lt;a href=&quot;http://www.facebook.com/&quot;&gt;Facebook &lt;/a&gt;, &lt;a href=&quot;http://slashdot.org/&quot;&gt;Slashdot &lt;/a&gt; and &lt;a href=&quot;http://www.wikipedia.org/&quot;&gt;Wikipedia &lt;/a&gt;. &lt;/p&gt;&lt;br /&gt;&lt;h4&gt;How it works &lt;/h4&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;  &lt;li&gt;Memcached consists of a server and a client part.. The server is a standalone program that runs on your servers and the client is in this case a PHP extension. &lt;/li&gt;&lt;br /&gt;  &lt;li&gt;If you have 3 webservers which all run Memcached, all webservers connect to all 3 memcached servers. The 3 memcache servers are all in the same &#39;pool&#39;. &lt;/li&gt;&lt;br /&gt;  &lt;li&gt;The cache servers all only contain part of the cache. Meaning, the cache is not replicated between the memcached servers. &lt;/li&gt;&lt;br /&gt;  &lt;li&gt;To find the server where the cache is stored (or should be stored) a so-called hashing algorithm is used. This way the &#39;right&#39; server is always picked. &lt;/li&gt;&lt;br /&gt;  &lt;li&gt;Every memcached server has a memory limit. It will never consume more memory than the limit. If the limit is exceeded, older cache is automatically thrown out (if the TTL is exceed or not). &lt;/li&gt;&lt;br /&gt;  &lt;li&gt;This means it cannot be used as a place to simply store data.. The database does that part. Don&#39;t confuse the purpose of the two! &lt;/li&gt;&lt;br /&gt;  &lt;li&gt;Memcached runs the fastest (like many other applications) on a Linux 2.6 kernel. &lt;/li&gt;&lt;br /&gt;  &lt;li&gt;By default, memcached is completely open.. Be sure to have a firewall in place to lock out outside ip&#39;s, because this can be a huge security risk. &lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;h4&gt;Installing &lt;/h4&gt;&lt;br /&gt;&lt;p&gt;When you are on debian/ubuntu, installing is easy: &lt;/p&gt;&lt;br /&gt;apt-get&amp;nbsp;install&amp;nbsp;memcached&lt;br /&gt;&lt;p&gt;You are stuck with a version though.. Debian tends to be slow in updates. Other distributions might also have a pre-build package for you. In any other case you might need to download Memcached from the &lt;a href=&quot;http://www.danga.com/memcached/download.bml&quot;&gt;site &lt;/a&gt; and compile it with the usual: &lt;/p&gt;&lt;br /&gt;./configure &lt;br&gt;&lt;br /&gt;make &lt;br&gt;&lt;br /&gt;make&amp;nbsp;install&lt;br /&gt;&lt;p&gt;There&#39;s probably a README in the package with better instructions. &lt;/p&gt;&lt;br /&gt;&lt;p&gt;After installation, you need the &lt;a href=&quot;http://pecl.php.net/package/memcache&quot;&gt;Pecl extension &lt;/a&gt;. All you need to do for that (usually) is.. &lt;/p&gt;&lt;br /&gt;pecl&amp;nbsp;install&amp;nbsp;Memcache&lt;br /&gt;&lt;p&gt;You also need the zlib development library. For debian, you can get this by entering: &lt;/p&gt;&lt;br /&gt;apt-get&amp;nbsp;install&amp;nbsp;zlib1g-dev&lt;br /&gt;&lt;p&gt;However, 99% of the times automatic pecl installation fails for me. Here&#39;s the alternative installation instructions. &lt;/p&gt;&lt;br /&gt;pecl&amp;nbsp;download&amp;nbsp;Memcache &lt;br&gt;&lt;br /&gt;tar&amp;nbsp;xfvz&amp;nbsp;Memcache-2.1.0.tgz&amp;nbsp;#version&amp;nbsp;might&amp;nbsp;be&amp;nbsp;changed &lt;br&gt;&lt;br /&gt;cd&amp;nbsp;Memcache-2.1.0 &lt;br&gt;&lt;br /&gt;phpize &lt;br&gt;&lt;br /&gt;./configure &lt;br&gt;&lt;br /&gt;make &lt;br&gt;&lt;br /&gt;make&amp;nbsp;install&lt;br /&gt;&lt;p&gt;Don&#39;t forget to enable the extension in php.ini by adding the line &lt;em&gt;extension=memcache.so &lt;/em&gt; and restarting the webserver. &lt;/p&gt;&lt;br /&gt;&lt;h4&gt;The good stuff &lt;/h4&gt;&lt;br /&gt;&lt;p&gt;After the Memcached server is installed, running and you have PHP running with the Memcache extension, you&#39;re off.. Here&#39;s the Memcached class. &lt;/p&gt;&lt;br /&gt;&amp;lt;?php &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;class&amp;nbsp; Sabre_Cache_MemCache&amp;nbsp; extends&amp;nbsp; Sabre_Cache_Abstract&amp;nbsp; { &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;//&amp;nbsp;Memcache&amp;nbsp;object &lt;br&gt;&lt;br /&gt;public&amp;nbsp; $connection ; &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; function&amp;nbsp; __construct ()&amp;nbsp;{ &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;$this -&amp;gt; connection&amp;nbsp; =&amp;nbsp;new&amp;nbsp; MemCache ; &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; function&amp;nbsp; store ( $key ,&amp;nbsp; $data ,&amp;nbsp; $ttl )&amp;nbsp;{ &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return&amp;nbsp; $this -&amp;gt; connection -&amp;gt; set ( $key , $data , 0 , $ttl ); &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; function&amp;nbsp; fetch ( $key )&amp;nbsp;{ &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return&amp;nbsp; $this -&amp;gt; connection -&amp;gt; get ( $key ); &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; function&amp;nbsp; delete ( $key )&amp;nbsp;{ &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return&amp;nbsp; $this -&amp;gt; connection -&amp;gt; delete ( $key ); &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; function&amp;nbsp; addServer ( $host , $port&amp;nbsp; =&amp;nbsp; 11211 ,&amp;nbsp; $weight&amp;nbsp; =&amp;nbsp; 10 )&amp;nbsp;{ &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;$this -&amp;gt; connection -&amp;gt; addServer ( $host , $port , true , $weight ); &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;?&amp;gt;&lt;br /&gt;&lt;p&gt;Now, the only thing you have to do in order to use this class, is add servers. Add servers consistently! Meaning that every server should add the exact same memcache servers so the keys will distributed in the same way from every webserver. &lt;/p&gt;&lt;br /&gt;&lt;p&gt;If a server has double the memory available for memcached, you can double the weight. The chance that data will be stored on that specific server will also be doubled. &lt;/p&gt;&lt;br /&gt;&lt;h3&gt;Example &lt;/h3&gt;&lt;br /&gt;&amp;lt;?php &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $cache&amp;nbsp; =&amp;nbsp;new&amp;nbsp; Sabre_Cache_MemCache (); &lt;br&gt;&lt;br /&gt;$cache -&amp;gt; addServer ( &#39;www1&#39; ); &lt;br&gt;&lt;br /&gt;$cache -&amp;gt; addServer ( &#39;www2&#39; , 11211 , 20 );&amp;nbsp; //&amp;nbsp;this&amp;nbsp;server&amp;nbsp;has&amp;nbsp;double&amp;nbsp;the&amp;nbsp;memory,&amp;nbsp;and&amp;nbsp;gets&amp;nbsp;double&amp;nbsp;the&amp;nbsp;weight &lt;br&gt;&lt;br /&gt;$cache -&amp;gt; addServer ( &#39;www3&#39; , 11211 ); &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;//&amp;nbsp;Store&amp;nbsp;some&amp;nbsp;data&amp;nbsp;in&amp;nbsp;the&amp;nbsp;cache&amp;nbsp;for&amp;nbsp;10&amp;nbsp;minutes &lt;br&gt;&lt;br /&gt;$cache -&amp;gt; store ( &#39;my_key&#39; , &#39;foobar&#39; , 600 ); &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;//&amp;nbsp;Get&amp;nbsp;it&amp;nbsp;out&amp;nbsp;of&amp;nbsp;the&amp;nbsp;cache&amp;nbsp;again &lt;br&gt;&lt;br /&gt;echo( $cache -&amp;gt; fetch ( &#39;my_key&#39; )); &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;?&amp;gt;&lt;br /&gt;&lt;h3&gt;Some final tips &lt;/h3&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;  &lt;li&gt;Be sure to check out the docs for &lt;a href=&quot;http://www.php.net/memcache&quot;&gt;Memcache &lt;/a&gt; and &lt;a href=&quot;http://www.php.net/apc&quot;&gt;APC &lt;/a&gt; to and try to determine whats right for you. &lt;/li&gt;&lt;br /&gt;  &lt;li&gt;Caching can help everywhere SQL queries are done.. You&#39;d be surprised how big the difference can be in terms of speed.. &lt;/li&gt;&lt;br /&gt;  &lt;li&gt;In some cases you might want the cross-server abilities of memcached, but you don&#39;t want to use up your memory or have your items automatically get flushed out.. Wikipedia came across this problem and traded in fast memory caching for virtually infinite size file-based caching by creating a memcached-compatible engine, called &lt;a href=&quot;http://meta.wikimedia.org/wiki/Tugela_Cache&quot;&gt;Tugela Cache &lt;/a&gt;, so you can still use the Pecl Memcache client with this, so it should be pretty easy. I don&#39;t have experience with this or know how stable it is. &lt;/li&gt;&lt;br /&gt;  &lt;li&gt;If you have different requirements for different parts of your cache, you can always consider using the different types alongside. &lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;octopus east java baker&lt;/div&gt;</description><link>http://scriptster.blogspot.com/2007/11/caching-in-php-using-filesystem-apc-and.html</link><author>noreply@blogger.com (Octopus)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-2977499297091575918.post-5525437811367197904</guid><pubDate>Wed, 21 Nov 2007 08:04:00 +0000</pubDate><atom:updated>2007-11-21T00:07:39.114-08:00</atom:updated><title>Create a searchable Google map</title><description>&lt;p&gt;Google&#39;s Mark Lucokvsky shows you how to add search functionality to maps using the GSmapSearchControl Solution &lt;/p&gt;&lt;br /&gt;&lt;p&gt;The GSmapSearchControl Solution is a simple to use application of the &lt;a href=&quot;http://code.google.com/apis/ajaxsearch/index.html&quot;&gt;Google AJAX Search API &lt;/a&gt; that is designed to let you easily add a searchable map to your pages, sites and blogs. The rest of this page discusses this topic in detail - but if you just want to cut and paste some code, the “hello world” of the Map Search Control solution is available at the &lt;a href=&quot;http://www.thinkvitamin.com/features/ajax/create-a-searchable-google-map#hello-world&quot;&gt;end of this article &lt;/a&gt;. &lt;/p&gt;&lt;br /&gt;&lt;p&gt;This &lt;a href=&quot;http://www.thinkvitamin.com/basicgmapsearch.html&quot;&gt;basic sample &lt;/a&gt; demonstrates the following features: &lt;/p&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;  &lt;li&gt;A search control that allows you to look up addresses and business listings, plotting the results on a map. &lt;/li&gt;&lt;br /&gt;  &lt;li&gt;The search control has a programmable center point, and at this center point you can specify a custom title and url. &lt;/li&gt;&lt;br /&gt;  &lt;li&gt;The search control takes a small amount of verticle space while inactive, the inactive view is a small map with a white center point. &lt;/li&gt;&lt;br /&gt;  &lt;li&gt;Once a search completes, the map expands and the search result cursors allow you to scroll through the set of search results. &lt;/li&gt;&lt;br /&gt;  &lt;li&gt;Each search result contains a link to a details page for the result as well as a link to get driving directions from the center point of the map to the current search result. &lt;/li&gt;&lt;br /&gt;  &lt;li&gt;The clear button in the center of the cursor controls clears the current set of results and sets the control into the idle state. &lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;p&gt;The solution is designed for extreme ease of use. As a site designer you are able to control the center point location as well as a custom title and url. In addition, you can easily program a collection of “search links” that you can place on your page that when clicked, will drive the search control. &lt;/p&gt;&lt;br /&gt;&lt;h4&gt;New Functionality Update &lt;/h4&gt;&lt;br /&gt;&lt;p&gt;If you are already familiar with this solution, you might find the following new functionality helpful and useful. &lt;/p&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;  &lt;li&gt;&lt;a href=&quot;http://www.thinkvitamin.com/features/ajax/create-a-searchable-google-map#_setcentericon&quot;&gt;Custom Icons &lt;/a&gt;&lt;/li&gt;&lt;br /&gt;  &lt;li&gt;&lt;a href=&quot;http://www.thinkvitamin.com/features/ajax/create-a-searchable-google-map#_setzoomlevel&quot;&gt;Zoom Level Control &lt;/a&gt;&lt;/li&gt;&lt;br /&gt;  &lt;li&gt;&lt;a href=&quot;http://www.thinkvitamin.com/features/ajax/create-a-searchable-google-map#_setmaptype&quot;&gt;Enabling GMapTypeControl &lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;h4&gt;Instructions for adding this to your site &lt;/h4&gt;&lt;br /&gt;&lt;p&gt;Adding the solution is a simple three step process. &lt;/p&gt;&lt;br /&gt;&lt;h5&gt;Step 1 - Load AJAX Search API, the Google Maps API, and the Map Search Solution &lt;/h5&gt;&lt;br /&gt;&lt;p&gt;First you need to load the Google AJAX Search API, the Google Maps API, and the Map Search solution into your application. If you don&#39;t already have a Google AJAX Search API key, your first step is to &lt;a href=&quot;http://code.google.com/apis/ajaxsearch/signup.html&quot;&gt;sign up for a key &lt;/a&gt;. With your key in hand, add the following five lines of code to your page or blog template. &lt;/p&gt;&lt;br /&gt;&amp;lt;!-- maps api, ajax search api, map search solution code --&amp;gt; &amp;lt;script src=&quot;http://maps.google.com/maps?file=api&amp;amp;v=2&amp;amp;key=YOUR-KEY&quot; type=&quot;text/javascript&quot;&amp;gt;&amp;lt;/script&amp;gt; &amp;lt;script src=&quot;http://www.google.com/uds/api?file=uds.js&amp;amp;v=1.0&amp;amp;key=YOUR-KEY&quot; type=&quot;text/javascript&quot;&amp;gt;&amp;lt;/script&amp;gt; &amp;lt;script src=&quot;http://www.google.com/uds/solutions/mapsearch/gsmapsearch.js&quot; type=&quot;text/javascript&quot;&amp;gt;&amp;lt;/script&amp;gt; &amp;lt;!-- ajax search stylesheet, map search stylesheet --&amp;gt; &amp;lt;link href=&quot;http://www.google.com/uds/css/gsearch.css&quot; rel=&quot;stylesheet&quot; type=&quot;text/css&quot;/&amp;gt; &amp;lt;link href=&quot;http://www.google.com/uds/solutions/mapsearch/gsmapsearch.css&quot; rel=&quot;stylesheet&quot; type=&quot;text/css&quot;/&amp;gt;&lt;br /&gt;&lt;h5&gt;Step 2 - Define a location on your page for the Map Search Control &lt;/h5&gt;&lt;br /&gt;&lt;p&gt;The next step is to define a place on your page for the search control (note: you can have more than one). This is typically done by defining a named &amp;lt;div&amp;gt; element as we have shown below: &lt;/p&gt;&lt;br /&gt;&amp;lt;div id=&quot;mapsearch&quot;&amp;gt;Loading...&amp;lt;/div&amp;gt;&lt;br /&gt;&lt;p&gt;You might want to set some styling attributes on this element to constrain the width of the control, set a border or margin, etc. For example, a style rule like this might be useful. &lt;/p&gt;&lt;br /&gt;#mapsearch { width : 400px; margin : 10px; padding : 4px; border : 1px solid #f9f9f9; }&lt;br /&gt;&lt;p&gt;In addition to this base style, the height of the idle state map and the active state map is easily modified. &lt;/p&gt;&lt;br /&gt;/* set height of idle state map */ #mapsearch .gsmsc-idleMapDiv { height : 200px; } /* set height of active state map */ #mapsearch .gsmsc-mapDiv { height : 300px; }&lt;br /&gt;&lt;h5&gt;Step 3 - Create a GSmapSearchControl and bind it to your page &lt;/h5&gt;&lt;br /&gt;&lt;p&gt;The final step involves creating and configuring the control. The control is very powerful and offers several options. In this section, we will describe the simplest case of adding a control to your page or blog followed several examples that demonstrate more advanced concepts. &lt;/p&gt;&lt;br /&gt;&lt;p&gt;The first step is to actually get your code to run. The easiest way to do this is to either extend an existing body onload handler, or create a new one. Find the &amp;lt;body&amp;gt; element on your page and add an onload handler. &lt;/p&gt;&lt;br /&gt;&amp;lt;body onload=&quot;OnLoad()&quot;&amp;gt;&lt;br /&gt;&lt;p&gt;Now write your onload handler by adding some code to an existing &amp;lt;script&amp;gt; block, or by creating a new one. Find the &amp;lt;body&amp;gt; element on your page and add an onload handler. The code snippet below demonstrates how to create a new map search control that will appear on your page inside the element named “mapsearch”. The map will center itself on Google corporate headquarters located at “1600 Amphitheatre Parkway, Mountain View, CA.” &lt;/p&gt;&lt;br /&gt;&amp;lt;script type=&quot;text/javascript&quot;&amp;gt; function OnLoad() { new GSmapSearchControl( document.getElementById(&quot;mapsearch&quot;), // container &quot;1600 Amphitheatre Parkway, Mountain View, CA&quot;, // center point null // options ); } &amp;lt;/script&amp;gt;&lt;br /&gt;&lt;h4&gt;Options &lt;/h4&gt;&lt;br /&gt;&lt;p&gt;Notice in the above example, the value null is passed as the options argument, a Javascript object which is typically specified in object literal form. The following sections describe the possible values for options . These values support the following features: &lt;/p&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;  &lt;li&gt;Setting a special title and url for the map center point. &lt;/li&gt;&lt;br /&gt;  &lt;li&gt;Specifying a set of hot spots on your page that will trigger searches &lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;h5&gt;Setting a special title and url for the map center point &lt;/h5&gt;&lt;br /&gt;&lt;p&gt;A special title and url can be programmed into the control and bound to the white center point marker of an active map. A typical use case for this feature might be to specify a conference name and conference url, or a company name and url. In order to request this functionality, the title and url properties of the options argument must be set. The following code snippet demonstrates this. &lt;/p&gt;&lt;br /&gt;&amp;lt;script type=&quot;text/javascript&quot;&amp;gt; function OnLoad() { // set title to the Googleplex and the link to // the Google corporate information page var options = { title : &quot;Googleplex&quot;, url : &quot;http://www.google.com/corporate/index.html&quot; } // create the map search control new GSmapSearchControl( document.getElementById(&quot;mapsearch&quot;), &quot;1600 Amphitheatre Parkway, Mountain View, CA&quot;, options ); } &amp;lt;/script&amp;gt;&lt;br /&gt;&lt;h5&gt;Setting up hot spots &lt;/h5&gt;&lt;br /&gt;&lt;p&gt;A common use case for this control is program hot spots on to your page thatwhen clicked will drive the search control. These hot spots might take the form of a list of recommendations, hotels, restaurants, etc. The search control supports this by allowing you to program a list of HTML elements and associated queries. When your users click on the element, the search control is activated with the specified query. &lt;/p&gt;&lt;br /&gt;&lt;p&gt;The options argument contains an optional hotspot property. This property is an array of objects, where each object contains an element property which is a reference to an HTML element on your page, as well as a query property which specifies a query to execute when the element is clicked. &lt;/p&gt;&lt;br /&gt;&lt;p&gt;The following code fragment demonstrates the use of this feature including the CSS declarations,HTML fragments, and options programming. If you prefer programming this on your own, perhaps by using &amp;lt;a&amp;gt; tags with javascript: urls, that&#39;s a perfectly reasonable way to proceed. We include this capability in the solution because for some of our users, this is a simpler mechanism that requires less of their time to develop. In the snippet that follows we are going to show sample CSS, HTML, and search control initialization logic. &lt;/p&gt;&lt;br /&gt;/* define the CSS used to style the hotspots */ h4.hotspot { font-size : 100%; font-weight : normal; color : rgb(9, 122, 182); margin-left : 8px; margin-top : 0px; margin-bottom : 2px; font-style : normal; cursor : pointer; } h4.hotspot:hover { color : rgb(237, 92, 11); text-decoration : underline; } &amp;lt;!-- Define the HTML that places the hotspots on your page. Note, you can use any HTML element you like including li, div, etc. --&amp;gt; &amp;lt;div id=&quot;mapsearch&quot;&amp;gt;Loading...&amp;lt;/div&amp;gt; &amp;lt;h3 class=&quot;hotspotheader&quot;&amp;gt;Recommendations&amp;lt;/h3&amp;gt; &amp;lt;h4 id=&quot;hs01&quot; class=&quot;hotspot&quot;&amp;gt;Caffeine&amp;lt;/h4&amp;gt; &amp;lt;h4 id=&quot;hs02&quot; class=&quot;hotspot&quot;&amp;gt;Thai Food&amp;lt;/h4&amp;gt; &amp;lt;h4 id=&quot;hs03&quot; class=&quot;hotspot&quot;&amp;gt;Pizza&amp;lt;/h4&amp;gt; &amp;lt;h4 id=&quot;hs04&quot; class=&quot;hotspot&quot;&amp;gt;Gym&amp;lt;/h4&amp;gt; &amp;lt;h4 id=&quot;hs05&quot; class=&quot;hotspot&quot;&amp;gt;Hotel Avante&amp;lt;/h4&amp;gt; &amp;lt;h4 id=&quot;hs06&quot; class=&quot;hotspot&quot;&amp;gt;Residence Inn&amp;lt;/h4&amp;gt; &amp;lt;h4 id=&quot;hs07&quot; class=&quot;hotspot&quot;&amp;gt;The Four Seasons&amp;lt;/h4&amp;gt; &amp;lt;h4 id=&quot;hs08&quot; class=&quot;hotspot&quot;&amp;gt;The Westin, Palo Alto&amp;lt;/h4&amp;gt; &amp;lt;script type=&quot;text/javascript&quot;&amp;gt; function OnLoad() { // Create an array of hotspots. Each entry contains and html element // from your page, and the query to execute when that element is clicked var hotspotsList = [ { element : document.getElementById(&quot;hs01&quot;), query : &quot;Starbucks&quot; }, { element : document.getElementById(&quot;hs02&quot;), query : &quot;Amarin Thai&quot; }, { element : document.getElementById(&quot;hs03&quot;), query : &quot;Frankie Johnnie &amp;amp; Luigi&quot; }, { element : document.getElementById(&quot;hs04&quot;), query : &quot;Hotel Avante&quot; }, { element : document.getElementById(&quot;hs05&quot;), query : &quot;Residence Inn&quot; }, { element : document.getElementById(&quot;hs06&quot;), query : &quot;Four Seasons Palo Alto&quot; }, { element : document.getElementById(&quot;hs07&quot;), query : &quot;Westin Palo Alto&quot; } ]; // set title to the Googleplex and the link to // the Google corporate information page // set the hotspot list to the list above var options = { title : &quot;Googleplex&quot;, url : &quot;http://www.google.com/corporate/index.html&quot;, hotspots : hotspotsList } // create the map search control new GSmapSearchControl( document.getElementById(&quot;mapsearch&quot;), &quot;1600 Amphitheatre Parkway, Mountain View, CA&quot;, options ); } &amp;lt;/script&amp;gt;&lt;br /&gt;&lt;h5&gt;New! Setting Custom Center Icon &lt;/h5&gt;&lt;br /&gt;&lt;p&gt;Applications can either accept the default center location icon, or they can supply their own GIcon and the system will use that Icon to mark the center point of the map. &lt;/p&gt;&lt;br /&gt;&lt;p&gt;The options argument contains an optional centerIcon property. When supplied, property must specify a valid &lt;a href=&quot;http://www.google.com/apis/maps/documentation/reference.html#GIcon&quot;&gt;GIcon &lt;/a&gt;. When specified, this icon is used as the center point marker for both the idle and active map. &lt;/p&gt;&lt;br /&gt;&lt;p&gt;The following code fragment demonstrates the use of this feature. It demonstrates the use of both a hand built icon, as well as the G_DEFAULT_ICON two calls: &lt;/p&gt;&lt;br /&gt;// use the ridefinder, small yellow icon as the center point marker var ci = new GIcon(); ci.image = &quot;http://labs.google.com/ridefinder/images/mm_20_yellow.png&quot;; ... (rest of initialization omitted) new GSmapSearchControl(container, &quot;1600 Amphitheatre Parkway, Mountain View, CA&quot;, { title : &quot;Googleplex&quot;, url : &quot;http://www.google.com/press/factorytour.html&quot;, centerIcon : ci } ); // use the G_DEFAULT_ICON as the center point marker new GSmapSearchControl(container, &quot;1600 Amphitheatre Parkway, Mountain View, CA&quot;, { title : &quot;Googleplex&quot;, url : &quot;http://www.google.com/press/factorytour.html&quot;, centerIcon : G_DEFAULT_ICON } );&lt;br /&gt;&lt;h5&gt;New! Setting Custom Selected and Unselected Icons &lt;/h5&gt;&lt;br /&gt;&lt;p&gt;Applications are able to specify the icons for the currently selected search result as well as for all unselected search results using a similar model. &lt;/p&gt;&lt;br /&gt;&lt;p&gt;The options argument contains an optional selectedIcon property. When supplied, property must specify a valid &lt;a href=&quot;http://www.google.com/apis/maps/documentation/reference.html#GIcon&quot;&gt;GIcon &lt;/a&gt;. When specified, this icon is used as the marker for the selected search result. &lt;/p&gt;&lt;br /&gt;&lt;p&gt;The options argument contains an optional unselectedIcon property. When supplied, property must specify a valid &lt;a href=&quot;http://www.google.com/apis/maps/documentation/reference.html#GIcon&quot;&gt;GIcon &lt;/a&gt;. When specified, this icon is used as the marker for all other search results. &lt;/p&gt;&lt;br /&gt;&lt;p&gt;The following code fragment demonstrates the use of this feature: &lt;/p&gt;&lt;br /&gt;// use the G_DEFAULT_ICON as the for selected and unselected search results new GSmapSearchControl(container, &quot;1600 Amphitheatre Parkway, Mountain View, CA&quot;, { title : &quot;Googleplex&quot;, url : &quot;http://www.google.com/press/factorytour.html&quot;, selectedIcon : G_DEFAULT_ICON, unselectedIcon : G_DEFAULT_ICON } );&lt;br /&gt;&lt;h5&gt;Controlling the Zoom Level &lt;/h5&gt;&lt;br /&gt;&lt;p&gt;Applications can control the Zoom Level for the idle map (displayed when no searches are active) as well as for the active map (displayed when a map is showing results). The system defines two constants that are helpful when configuring this aspect of the control: &lt;/p&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;  &lt;li&gt;GSmapSearchControl.IDLE_MAP_ZOOM - the default zoom level for the idle map &lt;/li&gt;&lt;br /&gt;  &lt;li&gt;GSmapSearchControl.ACTIVE_MAP_ZOOM - the default zoom level for the active map &lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;p&gt;The options argument contains an optional idleMapZoom property. When supplied, this property specifies the zoom level for the idle map. A common use of this property is to have the idle map&#39;s zoom level match the default zoom level for the active map. In order to do this, use the constants described above to set idleMapZoom to GSmapSearchControl.ACTIVE_MAP_ZOOM . &lt;/p&gt;&lt;br /&gt;&lt;p&gt;The zoom level for the active map is controlled in a similar manner. The options argument contains an optional activeMapZoom property. When supplied, this property specifies the zoom level for the active map. Note: Applications can use these properties independently of each other. &lt;/p&gt;&lt;br /&gt;&lt;p&gt;The following code fragment demonstrates the use of this feature. &lt;/p&gt;&lt;br /&gt;// set the idle map zoom so that it matches the // default active map zoom level new GSmapSearchControl(container, &quot;1600 Amphitheatre Parkway, Mountain View, CA&quot;, { title : &quot;Googleplex&quot;, url : &quot;http://www.google.com/press/factorytour.html&quot;, idleMapZoom : GSmapSearchControl.ACTIVE_MAP_ZOOM } ); // set the active map zoom level up by 1 new GSmapSearchControl(container, &quot;1600 Amphitheatre Parkway, Mountain View, CA&quot;, { title : &quot;Googleplex&quot;, url : &quot;http://www.google.com/press/factorytour.html&quot;, activeMapZoom : GSmapSearchControl.ACTIVE_MAP_ZOOM+1 } );&lt;br /&gt;&lt;h5&gt;New! Enabling the Map Type Control &lt;/h5&gt;&lt;br /&gt;&lt;p&gt;The default behavior of the maps created by this control is for them to not contain the GMapTypeControl , the control that allows switching between map, hybrid and satellite mode. This behavior is programmable allowing applications to cause the control to build maps with the GMapTypeControl available on all maps, or just on the active map. &lt;/p&gt;&lt;br /&gt;&lt;p&gt;The options argument contains an optional mapTypeControl property. When supplied, this property specifies which maps should be programmed to include the GMapTypeControl . &lt;/p&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;  &lt;li&gt;GSmapSearchControl.MAP_TYPE_ENABLE_ACTIVE - When this value is specified for the mapTypeControl property, the active map will contain a GMapTypeControl &lt;/li&gt;&lt;br /&gt;  &lt;li&gt;GSmapSearchControl.MAP_TYPE_ENABLE_ALL - When this value is specified for the mapTypeControl property, both the active map and the idle map will contain a GMapTypeControl &lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;p&gt;The following code fragment demonstrates the use of this feature. &lt;/p&gt;&lt;br /&gt;// enable a GMapTypeControl on the active map new GSmapSearchControl(container, &quot;1600 Amphitheatre Parkway, Mountain View, CA&quot;, { title : &quot;Googleplex&quot;, url : &quot;http://www.google.com/press/factorytour.html&quot;, mapTypeControl : GSmapSearchControl.MAP_TYPE_ENABLE_ACTIVE } ); // enable a GMapTypeControl on the all maps new GSmapSearchControl(container, &quot;1600 Amphitheatre Parkway, Mountain View, CA&quot;, { title : &quot;Googleplex&quot;, url : &quot;http://www.google.com/press/factorytour.html&quot;, mapTypeControl : GSmapSearchControl.MAP_TYPE_ENABLE_ALL } );&lt;br /&gt;&lt;h4&gt;The “Hello World” of GSmapSearchControl &lt;/h4&gt;&lt;br /&gt;&lt;p&gt;The following page demonstrates a complete page which uses the GSmapSearchControl solution. You can start with this simple page, change internal to the value of your key and be up and running in seconds. &lt;/p&gt;&lt;br /&gt;&amp;lt;html&amp;gt; &amp;lt;head&amp;gt; &amp;lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html; charset=utf-8&quot;/&amp;gt; &amp;lt;title&amp;gt;GSmapSearchControl Sample&amp;lt;/title&amp;gt; &amp;lt;!-- Note: Make sure to replace the &amp;amp;key=internal with &amp;amp;key=YOUR-KEY in both the maps API script load and in the Ajax Search API script load statements --&amp;gt; &amp;lt;!-- maps api, ajax search api, map search solution code --&amp;gt; &amp;lt;script src=&quot;http://maps.google.com/maps?file=api&amp;amp;v=2&amp;amp;key=internal&quot; type=&quot;text/javascript&quot;&amp;gt;&amp;lt;/script&amp;gt; &amp;lt;script src=&quot;http://www.google.com/uds/api?file=uds.js&amp;amp;v=1.0&amp;amp;key=internal&quot; type=&quot;text/javascript&quot;&amp;gt;&amp;lt;/script&amp;gt; &amp;lt;script src=&quot;http://www.google.com/uds/solutions/mapsearch/gsmapsearch.js&quot; type=&quot;text/javascript&quot;&amp;gt;&amp;lt;/script&amp;gt; &amp;lt;!-- ajax search stylesheet, map search stylesheet --&amp;gt; &amp;lt;link href=&quot;http://www.google.com/uds/css/gsearch.css&quot; rel=&quot;stylesheet&quot; type=&quot;text/css&quot;/&amp;gt; &amp;lt;link href=&quot;http://www.google.com/uds/solutions/mapsearch/gsmapsearch.css&quot; rel=&quot;stylesheet&quot; type=&quot;text/css&quot;/&amp;gt; &amp;lt;style type=&quot;text/css&quot;&amp;gt; body, table, p{ background-color: white; font-family: Arial, sans-serif; font-size: 13px; } #mapsearch { width : 400px; margin-left: 10px; padding: 4px; border : 1px solid #f9f9f9; } &amp;lt;/style&amp;gt; &amp;lt;script type=&quot;text/javascript&quot;&amp;gt; function OnLoad() { var options = { title : &quot;Googleplex&quot;, url : &quot;http://www.google.com/corporate/index.html&quot; } new GSmapSearchControl( document.getElementById(&quot;mapsearch&quot;), &quot;1600 Amphitheatre Parkway, Mountain View, CA&quot;, options ); } &amp;lt;/script&amp;gt; &amp;lt;/head&amp;gt; &amp;lt;body onload=&quot;OnLoad()&quot;&amp;gt; &amp;lt;div id=&quot;mapsearch&quot;&amp;gt;Loading...&amp;lt;/div&amp;gt; &amp;lt;/body&amp;gt; &amp;lt;/html&amp;gt;&lt;br /&gt;&lt;h4&gt;Examples &lt;/h4&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;  &lt;li&gt;&lt;a href=&quot;http://www.thinkvitamin.com/basicgmapsearch.html&quot;&gt;Basic Google Map Search &lt;/a&gt;&lt;/li&gt;&lt;br /&gt;  &lt;li&gt;&lt;a href=&quot;http://www.thinkvitamin.com/gmapsearchhotspots.html&quot;&gt;‘Hotspots&#39; Google Map Search &lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;octopus east java baker&lt;/div&gt;</description><link>http://scriptster.blogspot.com/2007/11/create-searchable-google-map.html</link><author>noreply@blogger.com (Octopus)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-2977499297091575918.post-5495669375629030134</guid><pubDate>Wed, 21 Nov 2007 08:01:00 +0000</pubDate><atom:updated>2007-11-21T00:03:03.751-08:00</atom:updated><title>15 Things you can do with Yahoo! UI</title><description>&lt;p&gt;write by :&lt;a href=&quot;http://www.thinkvitamin.com/advisors/dustin_diaz.php&quot;&gt;&lt;span&gt;Dustin Diaz &lt;/span&gt;&lt;/a&gt;&lt;a href=&quot;http://www.dustindiaz.com/&quot;&gt;dustindiaz.com&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Slicken up your web apps with these tips and tricks using the Yahoo! User Interface library &lt;/p&gt;                 &lt;p&gt;I will admit straight up front - I don’t like writing long articles. There, I said it. I passed College English convincing my professors that I should be rewarded more for my creativity rather than the length of my prose. I’m the kind of guy that spent more time writing short stories than huge complicated essays. Eventually I went on to write for the school Newspaper, a.k.a. &lt;a href=&quot;http://www.statehornet.com/&quot; title=&quot;CSU Sacramento&#39;s Student Newspaper&quot;&gt;The State Hornet&lt;/a&gt; which gave me the freedom to keep my stories to a minimum of 500 words, or just a couple of paragraphs.&lt;/p&gt; &lt;p&gt;Today that legacy still stands and has transferred into my love for making widgets. No, not &lt;a href=&quot;http://widgets.yahoo.com/&quot; title=&quot;Previously known as Konfabulator&quot;&gt;those widgets&lt;/a&gt;. I’m talking about those little goofy things you do on a Sunday afternoon from when you had that idea on Saturday night which left you frustrated on Friday after work. Yes, you’re not the only one with crazy ideas.&lt;/p&gt; &lt;p&gt;I’m talking about sliders, yoyos, tooltips, shakers, better looking code, faster queries, and random jubilees of DOM hoopla. It’s those small things that some of us live to create and find it rewarding even if it’s one line of code. And although these little works of ‘code art’ don’t always work on all browsers while having labels of ‘experimental’ written all over them, don’t feel ashamed of them. They come from you and you should embrace your work. You are, a Web Professional.&lt;/p&gt; &lt;h3&gt;Segue&lt;/h3&gt; &lt;p&gt;In this article I’m going to share some of my &lt;q&gt;short stories&lt;/q&gt;, &lt;q&gt;poems&lt;/q&gt;, and random sonnets of affectionate escapades I’ve had with JavaScript during the last few months, which I’ve built using the &lt;a href=&quot;http://developer.yahoo.com/yui&quot; title=&quot;Yahoo. Woot!&quot;&gt;Yahoo UI&lt;/a&gt; utilities. Some are rather embarrassing, others useful, and yet others I feel are just downright sexy. If you see something you like, feel free to take it, tweak it, and make it your own. This is what some poetry afficionados of secret societies would call a &lt;q&gt;poetry slam&lt;/q&gt;. So for want of a better phrase, this can be a &lt;code&gt;&lt;code&gt;&lt;/code&gt;.&lt;/code&gt;&lt;/p&gt; &lt;h3&gt;Why YUI?&lt;/h3&gt; &lt;p&gt;The &lt;abbr title=&quot;Yahoo User Interface&quot;&gt;YUI&lt;/abbr&gt; utilities give me the expressive freedom to do what I want. And although comparing libraries is generally silly, the best illustration I can give is the &lt;a href=&quot;http://script.aculo.us/&quot;&gt;Script.aculo.us&lt;/a&gt; Effects library vs the &lt;a href=&quot;http://developer.yahoo.com/yui/animation&quot;&gt;YUI Animation utility&lt;/a&gt;. Script.aculo.us offers you some pretty sweet looking effects like Fade, SlideUp, BlindDown, Shake, etc.. You can even add Parallel effects (way to go Thomas). On the flip side, the animation util doesn’t aim to give you these canned effects to package up with your web app, but rather it lets you make up your own effects by giving you the finely crafted tools (like a utility knife) to make what you want. &lt;/p&gt; &lt;p&gt;Another reason I like YUI is that it isn’t out to change the language itself, but rather it solves many of the cross-browser incompatibilities that we run into on a daily basis. Beyond that, it does quite a few other sexy things that I think you might like.&lt;/p&gt; &lt;h3&gt;Code&lt;/h3&gt; &lt;p&gt;Below is a compilation of fifteen things that I have either developed over the last few months, or have been inspired by a friend (who will receive full credit on the original idea). &lt;strong&gt;Enjoy!&lt;/strong&gt;&lt;/p&gt; &lt;h4&gt;DOM + The getElementBy’s&lt;/h4&gt; &lt;p&gt;These days, when you’re working with the DOM, it’s all about getting the elements you want, with conditions applied. Thankfully the Dom util doesn’t go all out and try to do all the guesswork for you resulting in a bulky library with large sets of unwanted code. Instead it gives you a handy method for you to work with called &lt;code&gt;getElementsBy&lt;/code&gt;.&lt;/p&gt; &lt;h4&gt;YAHOO.util.Dom.getElementsByClassName&lt;/h4&gt; &lt;p&gt;Let’s kick off our slam with the classic &lt;code&gt;getElementsByClassName&lt;/code&gt; (which is actually in the utility by default). I like to think of it as our token example by the YUI folks showing off how &lt;code&gt;getElementsBy&lt;/code&gt; can work natively within your functions. &lt;a href=&quot;http://www.thinkvitamin.com/misc/yui-demos/demo-01.html&quot;&gt;See Demo&lt;/a&gt;&lt;/p&gt; &lt;h4&gt;getElementsByAttribute&lt;/h4&gt; &lt;p&gt;This method is not in the Dom util by default, but demonstrates exactly how we can add it in if we wanted. &lt;a href=&quot;http://www.thinkvitamin.com/misc/yui-demos/demo-02.html&quot;&gt;See Demo&lt;/a&gt;&lt;/p&gt; &lt;h4&gt;getElementsByExternal &amp;amp; getElementsByInternal&lt;/h4&gt; &lt;p&gt;This function allows you to get outbound or inbound links returned to you as an HTMLElement collection. At that point it’s up to you what you want to do with your array of elements (eg. bind event listeners or run a method against them). Currently this is untested on IP address URIs, but I presume that won’t be an issue for most situations. &lt;a href=&quot;http://www.thinkvitamin.com/misc/yui-demos/demo-03.html&quot;&gt;See Demo&lt;/a&gt;&lt;/p&gt; &lt;h3&gt;Random Effects of Love&lt;/h3&gt; &lt;p&gt;Because everyone enjoys California cheese.&lt;/p&gt; &lt;h4&gt;Pagination Slide Pattern&lt;/h4&gt; &lt;p&gt;Paginating through large data sets and keeping someone’s attention can be a tedious task. Sliding results within a container is one way to keep a person entertained. &lt;a href=&quot;http://www.thinkvitamin.com/misc/yui-demos/demo-04.html&quot;&gt;See Demo&lt;/a&gt;&lt;/p&gt; &lt;h4&gt;BlindUp &amp;amp; BlindDown (Yoyo)&lt;/h4&gt; &lt;p&gt;These are classic effects that almost any animation lover would want in their toolkit. For the sake of making them a macro, here they are. &lt;a href=&quot;http://www.thinkvitamin.com/misc/yui-demos/demo-05.html&quot;&gt;See Demo&lt;/a&gt;&lt;/p&gt; &lt;h4&gt;BlindOut&lt;/h4&gt; &lt;p&gt;A demonstration of animating a box from any given corner. &lt;a href=&quot;http://www.thinkvitamin.com/misc/yui-demos/demo-06.html&quot;&gt;See Demo&lt;/a&gt;&lt;/p&gt; &lt;h4&gt;Faux Mutation Events with CustomEvent&lt;/h4&gt; &lt;p&gt;Most folk don’t know what mutation events are, mainly because they don’t work in IE6. These are events just like regular DOM events like ‘click’,&#39;mouseover’, or ‘mouseout’ that you can listen for. Just to name a few there are ‘DOMNodeInserted’, ‘DOMNodeRemoved’, and ‘DOMNodeInsertedIntoDocument’. For a better reference you can see &lt;a href=&quot;http://en.wikipedia.org/wiki/DOM_Events&quot;&gt;Wikipedia’s entry on DOM events&lt;/a&gt; and search for the Mutation events within the event table. Anyway, here’s how you can simulate some of those events using the CustomEvent class.&lt;/p&gt; &lt;h4&gt;DOMNodeInserted&lt;/h4&gt; &lt;p&gt;Create some elements, listen for the event, then make them draggable. &lt;a href=&quot;http://www.thinkvitamin.com/misc/yui-demos/demo-07.html&quot;&gt;See Demo&lt;/a&gt;&lt;/p&gt; &lt;h4&gt;DOMNodeRemoved&lt;/h4&gt; &lt;p&gt;Create some elements, then remove them to update an information box. &lt;a href=&quot;http://www.thinkvitamin.com/misc/yui-demos/demo-08.html&quot;&gt;See Demo&lt;/a&gt;&lt;/p&gt; &lt;h4&gt;More with CustomEvents&lt;/h4&gt; &lt;p&gt;There really is an endless amount of Custom Events that you can create. So we’ll keep this to a minimum. Here are three places that the CustomEvent can come in useful:&lt;/p&gt; &lt;h4&gt;Extending the Drag and Drop&lt;/h4&gt; &lt;p&gt;Currently, the Drag and Drop utility is packaged with quite a few custom events you can override such as &lt;code&gt;startDrag&lt;/code&gt;, &lt;code&gt;onDrag&lt;/code&gt;, or &lt;code&gt;endDrag&lt;/code&gt;. However the problem is that you can’t subscribe to any of these, only override. Here is one trick you can use to make them &lt;q&gt;subscribable&lt;/q&gt;. &lt;a href=&quot;http://www.thinkvitamin.com/misc/yui-demos/demo-09.html&quot;&gt;See Demo&lt;/a&gt;&lt;/p&gt; &lt;h4&gt;onMenuOpen &amp;amp; onMenuCollapse&lt;/h4&gt; &lt;p&gt;This is a combination of animation and custom events where we show menu items sliding into view and firing off subscribable events. &lt;a href=&quot;http://www.thinkvitamin.com/misc/yui-demos/demo-10.html&quot;&gt;See Demo&lt;/a&gt;&lt;/p&gt; &lt;h3&gt;General Recipes&lt;/h3&gt; &lt;p&gt;None of these have any rhyme or reason. But I tend to think that in some place or another, they can solve a problem.&lt;/p&gt; &lt;h4&gt;Sweet Titles (YUI Style)&lt;/h4&gt; &lt;p&gt;Here we have an OO version of &lt;a href=&quot;http://www.dustindiaz.com/sweet-titles/&quot;&gt;Sweet Titles&lt;/a&gt; that allows us to declare multiple instances of tooltips on separate elements with some optional configuration parameters you can pass into the constructor object to get that exact look and feel you want out of a tooltip. &lt;a href=&quot;http://www.thinkvitamin.com/misc/yui-demos/demo-11.html&quot;&gt;See Demo&lt;/a&gt;&lt;/p&gt; &lt;h4&gt;Faux Lightbox Effect&lt;/h4&gt; &lt;p&gt;For the sake of doing something that’s already been done, here’s a faux light box effect that can be obtained using some core tools. &lt;a href=&quot;http://www.thinkvitamin.com/misc/yui-demos/demo-12.html&quot;&gt;See Demo&lt;/a&gt;&lt;/p&gt; &lt;h4&gt;Photo Batching&lt;/h4&gt; &lt;p&gt;&lt;code&gt;YAHOO.util.Dom.batch&lt;/code&gt; alone may convince you of how cool the DOM Collection utility can be. This shows you how you can batch an HTML Element collection to a method. (Thanks Matt Sweeny) &lt;a href=&quot;http://www.thinkvitamin.com/misc/yui-demos/demo-13.html&quot;&gt;See Demo&lt;/a&gt;&lt;/p&gt; &lt;h4&gt;Unobtrusive new windows links&lt;/h4&gt; &lt;p&gt;For some reason or another, this always seems to create some noise regardless of its controversial nature. Here is a very simple way to do it with Event, DOM, and some of the tools we’ve defined in this very article. &lt;a href=&quot;http://www.thinkvitamin.com/misc/yui-demos/demo-14.html&quot;&gt;See Demo&lt;/a&gt;&lt;/p&gt; &lt;h4&gt;Layout Switching with Grids&lt;/h4&gt; &lt;p&gt;This is a combination of using the CSS Grids toolkit and swapping out the templates using JavaScript animation &lt;a href=&quot;http://www.thinkvitamin.com/misc/yui-demos/demo-15.html&quot;&gt;See Demo&lt;/a&gt;&lt;/p&gt; &lt;h3&gt;That’s All Folks&lt;/h3&gt; &lt;p&gt;At least for this article’s sake. There are plenty of other things you can making using the Yahoo! UI utilities and this has only scratched the surface. I hope it was as fun for you as it was for me.&lt;/p&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;octopus east java baker&lt;/div&gt;</description><link>http://scriptster.blogspot.com/2007/11/15-things-you-can-do-with-yahoo-ui.html</link><author>noreply@blogger.com (Octopus)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-2977499297091575918.post-4530609319179267685</guid><pubDate>Wed, 21 Nov 2007 07:55:00 +0000</pubDate><atom:updated>2007-11-20T23:58:21.100-08:00</atom:updated><title>Application logic versus template logic</title><description>&lt;p&gt; By Quentin Zervaas, 1 May 2006 &lt;/p&gt;&lt;br /&gt;&lt;p&gt;This article takes a look at separating application logic from template logic. We will use the &lt;a href=&quot;http://smarty.php.net&quot;&gt;Smarty Template Engine &lt;/a&gt; as the basis for the article and its examples. &lt;/p&gt;&lt;br /&gt;&lt;p&gt;What this is basically saying is that anything relating to the final output should be determined in the template, while any data handling or processing should be done in your PHP files and classes. There&#39;s a little more to it than though, which we&#39;ll soon see. &lt;/p&gt;&lt;br /&gt;&lt;p&gt;An important aspect of this is that it works both ways. Often people focus on making sure their templates don&#39;t do anything application related, but then make the mistake of making their PHP scripts (or classes) doing work that their templates should be doing. We will look at both situations and common issues that arise. &lt;/p&gt;&lt;br /&gt;&lt;h2&gt;What is application logic? &lt;/h2&gt;&lt;br /&gt;&lt;p&gt;Application logic (also called business logic) is any code that deals with processing of data. That is, the processing behind the scenes. Common examples of this include: &lt;/p&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;  &lt;li&gt;Processing the input from a web form &lt;/li&gt;&lt;br /&gt;  &lt;li&gt;Saving data to a database &lt;/li&gt;&lt;br /&gt;  &lt;li&gt;Debiting money from a credit card &lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;  &lt;li&gt;Reading or writing cookies on the client&#39;s computer&lt;br /&gt;      &lt;p&gt;This even includes instantiating the Smarty class and displaying a template: &lt;/p&gt;&lt;br /&gt;      &lt;h4&gt;Highlight: PHP &lt;/h4&gt;&lt;br /&gt;  &amp;lt;?php $smarty = new Smarty () ; $smarty -&amp;gt; display ( &#39; index.tpl &#39; ) ; ?&amp;gt;&lt;br /&gt;      &lt;p&gt;It also includes generating data that may be used in your template logic, but we&#39;ll look at that in a little while. &lt;/p&gt;&lt;br /&gt;      &lt;h2&gt;What is template logic? &lt;/h2&gt;&lt;br /&gt;      &lt;p&gt;Template logic (also called display logic) is any code in your templates that determines how things are displayed. For instance, if you output a certain message if a string is empty, or the string if it isn&#39;t empty, then this is template logic. Here&#39;s an example: &lt;/p&gt;&lt;br /&gt;      &lt;h4&gt;Highlight: Smarty Template &lt;/h4&gt;&lt;br /&gt;      {if $name|strlen == 0) &amp;lt; p &amp;gt; You didn&#39;t enter your name! &amp;lt; p &amp;gt; {else} &amp;lt; p &amp;gt; Hello {$name} &amp;lt;/ p &amp;gt; {/if}&lt;br /&gt;      &lt;p&gt;Formatting of a string is also template logic (although there may be exceptions, depending on the data). For example: &lt;/p&gt;&lt;br /&gt;      &lt;h4&gt;Highlight: Smarty Template &lt;/h4&gt;&lt;br /&gt;  &amp;lt; p &amp;gt; Title: {$title|strtoupper} Summary: {$summary|truncate} &amp;lt;/ p &amp;gt;&lt;br /&gt;      &lt;p&gt;We&#39;ll look at some more examples of application logic and template logic shortly, for now, we&#39;ll look at things that aren&#39;t application logic and aren&#39;t template logic. &lt;/p&gt;&lt;br /&gt;      &lt;h2&gt;Application logic in templates—bad! &lt;/h2&gt;&lt;br /&gt;      &lt;p&gt;Smarty allows developers to directly embed PHP code by using the {php} {/php} tag. Personally, while it&#39;s good to have the functionality available, I think it&#39;s almost always a bad idea to ever use this. It is also possible to use any declared PHP function (builtin or user defined) as a modifier (unless you have template security turned on). &lt;/p&gt;&lt;br /&gt;      &lt;p&gt;An example would be to directly access some data from a form and sanitize it in the template: &lt;/p&gt;&lt;br /&gt;      &lt;h4&gt;Highlight: Smarty Template &lt;/h4&gt;&lt;br /&gt;  &amp;lt; p &amp;gt; This is bad, but you entered {$smarty.get.name|strip_tags|trim}. &amp;lt;/ p &amp;gt;&lt;br /&gt;      &lt;p&gt;The way this should be done is done in the PHP file, and then passing the sanitized value to the template: &lt;/p&gt;&lt;br /&gt;      &lt;h4&gt;Highlight: PHP &lt;/h4&gt;&lt;br /&gt;  &amp;lt;?php require_once ( &#39; Smarty.class.php &#39; ) ; $name = trim ( strip_tags ( $_GET [ &#39; name &#39; ])) ; $smarty = new Smarty () ; $smarty -&amp;gt; assign ( &#39; name &#39; , $name ) ; $smarty -&amp;gt; display ( &#39; example.tpl &#39; ) ; ?&amp;gt;&lt;br /&gt;      &lt;p&gt;And then the template would look like: &lt;/p&gt;&lt;br /&gt;      &lt;h4&gt;Highlight: Smarty Template &lt;/h4&gt;&lt;br /&gt;  &amp;lt; p &amp;gt; This is good. You entered {$name}. &amp;lt;/ p &amp;gt;&lt;br /&gt;      &lt;h2&gt;Examples of acceptable logic in templates &lt;/h2&gt;&lt;br /&gt;      &lt;p&gt;So now that I&#39;ve covered a few bad things, what kinds of things are acceptable? Here are some examples. &lt;/p&gt;&lt;br /&gt;      &lt;h3&gt;Checking a string value or boolean flag (or string length, etc.) to determine what to output: &lt;/h3&gt;&lt;br /&gt;      &lt;h4&gt;Highlight: Smarty Template &lt;/h4&gt;&lt;br /&gt;      {if $name|strlen &amp;gt; 8} &amp;lt; p &amp;gt; Your name is long! &amp;lt;/ p &amp;gt; {/if} {if $male} &amp;lt; img src = &quot; male.gif &quot; /&amp;gt; {else} &amp;lt; img src = &quot; female.gif &quot; /&amp;gt; {/if}&lt;br /&gt;      &lt;h3&gt;Alternating background colours &lt;/h3&gt;&lt;br /&gt;      &lt;p&gt;Actually, this is made easy in Smarty with the {cycle} function: &lt;/p&gt;&lt;br /&gt;      &lt;h4&gt;Highlight: Smarty Template &lt;/h4&gt;&lt;br /&gt;  &amp;lt; table &amp;gt; &amp;lt; tr &amp;gt; &amp;lt; th &amp;gt; Field 1 &amp;lt;/ th &amp;gt; &amp;lt; th &amp;gt; Field 2 &amp;lt;/ th &amp;gt; &amp;lt;/ tr &amp;gt; {foreach from=$data item=row} &amp;lt; tr style = &quot; background: {cycle values=&#39;#ccc,#ddd&#39;} &quot; &amp;gt; &amp;lt; td &amp;gt; {$row.field1} &amp;lt;/ td &amp;gt; &amp;lt; td &amp;gt; {$row.field2} &amp;lt;/ td &amp;gt; &amp;lt;/ tr &amp;gt; {/foreach} &amp;lt;/ table &amp;gt;&lt;br /&gt;      &lt;h3&gt;Displaying a running count &lt;/h3&gt;&lt;br /&gt;      &lt;p&gt;This is also made easy in Smarty, using the {counter} function. &lt;/p&gt;&lt;br /&gt;      &lt;h4&gt;Highlight: Smarty Template &lt;/h4&gt;&lt;br /&gt;      {foreach from=$items row=item} &amp;lt; p &amp;gt; Item number {counter}. {$item} &amp;lt;/ p &amp;gt; {/foreach}&lt;br /&gt;      &lt;h3&gt;Including another template &lt;/h3&gt;&lt;br /&gt;      &lt;p&gt;This will be required frequently, and as we point out next, the alternative to doing this is quite bad! &lt;/p&gt;&lt;br /&gt;      &lt;h4&gt;Highlight: Smarty Template &lt;/h4&gt;&lt;br /&gt;      {include file=&#39;header.tpl&#39;} &amp;lt; p &amp;gt; Example of including a header and a footer. &amp;lt;/ p &amp;gt; {include file=&#39;footer.tpl&#39;}&lt;br /&gt;      &lt;h2&gt;Template logic in applications &lt;/h2&gt;&lt;br /&gt;      &lt;p&gt;There are several situations where you may incorrectly end up using template logic in your application without even realising. &lt;/p&gt;&lt;br /&gt;      &lt;h3&gt;Case 1: displaying multiple template files &lt;/h3&gt;&lt;br /&gt;      &lt;p&gt;Take a look at this PHP code to output a single page: &lt;/p&gt;&lt;br /&gt;      &lt;h4&gt;Highlight: PHP &lt;/h4&gt;&lt;br /&gt;  &amp;lt;?php require_once ( &#39; Smarty.class.php &#39; ) ; $smarty = new Smarty () ; $smarty -&amp;gt; display ( &#39; header.tpl &#39; ) ; $smarty -&amp;gt; display ( &#39; example.tpl &#39; ) ; $smarty -&amp;gt; display ( &#39; footer.tpl &#39; ) ; ?&amp;gt;&lt;br /&gt;      &lt;p&gt;This is extremely bad! You have essentially hardcoded in your application that your templates are built by displaying a header, then the main content, and then the footer. The fact that your templates are split into 3 templates like this is a function of the templates, not of the application. &lt;/p&gt;&lt;br /&gt;      &lt;p&gt;The correct way to do this is: &lt;/p&gt;&lt;br /&gt;      &lt;h4&gt;Highlight: PHP &lt;/h4&gt;&lt;br /&gt;  &amp;lt;?php require_once ( &#39; Smarty.class.php &#39; ) ; $smarty = new Smarty () ; $smarty -&amp;gt; display ( &#39; example.tpl &#39; ) ; ?&amp;gt;&lt;br /&gt;      &lt;p&gt;And then the example.tpl file would like: &lt;/p&gt;&lt;br /&gt;      &lt;h4&gt;Highlight: Smarty Template &lt;/h4&gt;&lt;br /&gt;      {include file=&#39;header.tpl&#39;} &amp;lt; p &amp;gt; Example of including a header and a footer. &amp;lt;/ p &amp;gt; {include file=&#39;footer.tpl&#39;}&lt;br /&gt;      &lt;h3&gt;Case 2: Determining a style or an image in code and then assigning it to a template &lt;/h3&gt;&lt;br /&gt;      &lt;p&gt;Let&#39;s assume you&#39;re outputting a document and you want to show an image that says ‘new&#39; if it was submitted today, or an image that says ‘old&#39; if it was submitted earlier. &lt;/p&gt;&lt;br /&gt;      &lt;p&gt;It would be bad to specify this image in the code like so: &lt;/p&gt;&lt;br /&gt;      &lt;h4&gt;Highlight: PHP &lt;/h4&gt;&lt;br /&gt;  &amp;lt;?php require_once ( &#39; Smarty.class.php &#39; ) ; if ( $article -&amp;gt; isNew ) $image = &#39; new.gif &#39; ; else $image = &#39; old.gif &#39; ; $smarty = new Smarty () ; $smarty -&amp;gt; assign ( &#39; image &#39; , $image ) ; $smarty -&amp;gt; display ( &#39; example.tpl &#39; ) ; ?&amp;gt;&lt;br /&gt;      &lt;p&gt;Even worse would be: &lt;/p&gt;&lt;br /&gt;      &lt;h4&gt;Highlight: PHP &lt;/h4&gt;&lt;br /&gt;  &amp;lt;?php if ( $article -&amp;gt; isNew ) $image = &#39; &amp;lt;img src=&quot;new.gif&quot; alt=&quot;New&quot; /&amp;gt; &#39; ; else $image = &#39; &amp;lt;img src=&quot;old.gif&quot; alt=&quot;Old&quot; /&amp;gt; &#39; ; ?&amp;gt;&lt;br /&gt;      &lt;p&gt;It seems obvious, but I have seen it done. The correct way would be to pass the flag to the template and in the template determine which image to use: &lt;/p&gt;&lt;br /&gt;      &lt;h4&gt;Highlight: PHP &lt;/h4&gt;&lt;br /&gt;  &amp;lt;?php require_once ( &#39; Smarty.class.php &#39; ) ; $smarty = new Smarty () ; $smarty -&amp;gt; assign ( &#39; isNew &#39; , $article -&amp;gt; isNew ) ; $smarty -&amp;gt; display ( &#39; example.tpl &#39; ) ; ?&amp;gt;&lt;br /&gt;      &lt;p&gt;And the template: &lt;/p&gt;&lt;br /&gt;      &lt;h4&gt;Highlight: Smarty Template &lt;/h4&gt;&lt;br /&gt;      {if $isNew} &amp;lt; img src = &quot; new.gif &quot; alt = &quot; New &quot; /&amp;gt; {else} &amp;lt; img src = &quot; old.gif &quot; alt = &quot; New &quot; /&amp;gt; {/if}&lt;br /&gt;      &lt;p&gt;Afterall, the image is tied to display. You might change template sets or image sets, resulting a new filename. You should only have to change your templates, not your application code. &lt;/p&gt;&lt;br /&gt;      &lt;h2&gt;Exceptions &lt;/h2&gt;&lt;br /&gt;      &lt;p&gt;There are always going to be exceptions where you may need to put application logic in a template, or some circumstances that sit right on the fence. Here&#39;s an example: &lt;/p&gt;&lt;br /&gt;      &lt;h4&gt;Highlight: Smarty Template &lt;/h4&gt;&lt;br /&gt;  &amp;lt; input type = &quot; text &quot; name = &quot; title &quot; value = &quot; {$title|escape} &quot; /&amp;gt;&lt;br /&gt;      &lt;p&gt;In this situation, to deal with the fact a user might enter a quotation mark (”), we must escape the data. You could argue that this is application logic, but personally, I think this is directly related to the output of your HTML document, and so should be escaped when it is output. &lt;/p&gt;&lt;br /&gt;      &lt;p&gt;Another exception I can think of would be if you wanted to list news articles in your template, but you&#39;re not sure how many. That is, the number of articles shown is a function of the template. In one layout you might have room to fit three articles, but if you change templates, you might have room for 5. So how many articles do you assign? &lt;/p&gt;&lt;br /&gt;      &lt;p&gt;The only way to cover all bases would be to get every single article and assign them all to the template. This seems somewhat excessive. The way I have dealt with this in the past is to use a function call with the number of articles. This function directly calls the database, which as we have said is therefore application logic, but sometimes there&#39;s no easier way around things: &lt;/p&gt;&lt;br /&gt;      &lt;h4&gt;Highlight: Smarty Template &lt;/h4&gt;&lt;br /&gt;      {foreach from=$news-&amp;gt;getArticles(5) item=article} &amp;lt; h2 &amp;gt; {$article.headline} &amp;lt;/ h2 &amp;gt; {/foreach}&lt;br /&gt;      &lt;h2&gt;Common sense &lt;/h2&gt;&lt;br /&gt;      &lt;p&gt;You must use your own judgement when determining what should be in code and what should be in template. Take a look at this example of checking for an empty array: &lt;/p&gt;&lt;br /&gt;      &lt;h4&gt;Highlight: Smarty Template &lt;/h4&gt;&lt;br /&gt;      {assign var=&#39;numElements&#39; value=$myArray|@count} {if $numElements == 0} &amp;lt; p &amp;gt; The array is empty. &amp;lt;/ p &amp;gt; {else} &amp;lt; p &amp;gt; There are {$numElements} elements. &amp;lt;/ p &amp;gt; {/if}&lt;br /&gt;      &lt;p&gt;Strictly speaking, you should determine the count in PHP, and perhaps even a flag to check if it&#39;s empty: &lt;/p&gt;&lt;br /&gt;      &lt;h4&gt;Highlight: PHP &lt;/h4&gt;&lt;br /&gt;  &amp;lt;?php require_once ( &#39; Smarty.class.php &#39; ) ; $myArray = array ( 1 , 2 , 3 ) ; $numElements = count ( $myArray ) ; $isEmpty = $numElements == 0 ; $smarty = new Smarty () ; $smarty -&amp;gt; assign ( &#39; myArray &#39; , $myArray ) ; $smarty -&amp;gt; assign ( &#39; numElements &#39; , $numElements ) ; $smarty -&amp;gt; assign ( &#39; isEmpty &#39; , $isEmpty ) ; $smarty -&amp;gt; display ( &#39; example.tpl &#39; ) ; ?&amp;gt;&lt;br /&gt;      &lt;p&gt;And the example.tpl file: &lt;/p&gt;&lt;br /&gt;      &lt;h4&gt;Highlight: Smarty Template &lt;/h4&gt;&lt;br /&gt;      {if $isEmpty} &amp;lt; p &amp;gt; The array is empty. &amp;lt;/ p &amp;gt; {else} &amp;lt; p &amp;gt; There are {$numElements} elements. &amp;lt;/ p &amp;gt; {/if}&lt;br /&gt;      &lt;p&gt;Personally, I think the second method is overkill and I would always use the first method. The additional problem is that we don&#39;t necessarily know in the script what data the template requires. &lt;/p&gt;&lt;br /&gt;      &lt;p&gt;The fact that we do something in the template for an empty array is display specific, not something that needs to be known in the application. &lt;/p&gt;&lt;br /&gt;      &lt;h2&gt;Conclusion &lt;/h2&gt;&lt;br /&gt;      &lt;p&gt;In this article I explained the difference between application logic and template logic when using Smarty. Hopefully you found some simple ways to improve your template design, but also recognised that some complexities can arise when doing this and sometimes comprimises must be made. &lt;/p&gt;&lt;br /&gt;      &lt;p&gt;One (simplified) way to look at it is like this: &lt;/p&gt;&lt;br /&gt;      &lt;p&gt;You should be able to completely change templates, including all image files and CSS files, without having to touch any of your PHP files. &lt;/p&gt;&lt;br /&gt;      &lt;p&gt;All fundamental data required in your templates should be fetched or determined ahead of time and assigned to your templates (this doesn&#39;t include meta data, such as the length of a string, etc.). &lt;/p&gt;&lt;br /&gt;      &lt;h3&gt;Further reading &lt;/h3&gt;&lt;br /&gt;  &lt;/li&gt;&lt;br /&gt;  &lt;li&gt;&lt;a href=&quot;http://smarty.php.net&quot;&gt;Smarty Template Engine &lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;  &lt;li&gt;&lt;a href=&quot;http://smarty.php.net/whyuse.php&quot;&gt;Smarty – why use it? &lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;octopus east java baker&lt;/div&gt;</description><link>http://scriptster.blogspot.com/2007/11/application-logic-versus-template-logic.html</link><author>noreply@blogger.com (Octopus)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-2977499297091575918.post-6273657781864231873</guid><pubDate>Wed, 21 Nov 2007 07:51:00 +0000</pubDate><atom:updated>2007-11-20T23:52:44.147-08:00</atom:updated><title>URL Rewriting with ASP.NET 2.0</title><description>Introduction&lt;br /&gt;&lt;br /&gt;In this article, you will learn about URL Rewriting in ASP.NET 2.0. URL Rewriting was originally introduced by Apache as an extensions called mod_rewrite.  The concept of URL rewriting is simple. It allows you to rewrite URL from those ugly URL into a better URL and hence it will perform better in SEO.&lt;br /&gt;&lt;br /&gt;Most Search Engines will ignore those dynamic URL such as the one ended with querystring&lt;br /&gt;e.g http://www.worldofasp.net/displayproduct.aspx?ID=10&lt;br /&gt;Therefore if you like to have more hits and  traffic from search engine, consider of rewriting all those querystring url into normal URL.&lt;br /&gt;&lt;br /&gt;If you rewrite the URL above, you can actually rewrite it into more readable format&lt;br /&gt;e.g http://www.worldofasp.net/product10.aspx.&lt;br /&gt;or you can rewrite it to http://www.worldofasp.net/product/10.aspx.&lt;br /&gt;&lt;br /&gt;Search Engine robot will think that your dynamic page is a normal page and therefore it will crawl your page and your page will have a better search results.&lt;br /&gt;If you check all the page in Worldofasp.net or CodeProject.com, you can see that the web developer is using URL rewriting techniques.&lt;br /&gt;&lt;br /&gt;Main&lt;br /&gt;&lt;br /&gt;Microsoft .NET Framework 2.0 come with limited URL Rewriting Library support and you have to write your own URL Rewriting engine if you need complex URL rewriting for your website.&lt;br /&gt;&lt;br /&gt;The simplest URL Rewriting that you can achieve in seconds is by copy and paste the code below to your global.asax file.&lt;br /&gt;&lt;br /&gt;void Application_BeginRequest(Object sender, EventArgs e) &lt;br /&gt;{&lt;br /&gt; String strCurrentPath;&lt;br /&gt; String strCustomPath;&lt;br /&gt; strCurrentPath = Request.Path.ToLower();&lt;BR&gt;&lt;br /&gt; if (strCurrentPath.IndexOf(&quot;ID&quot;) &gt;= 0) &lt;br /&gt; {&lt;br /&gt;  strCustomPath = &quot;/Product10.aspx&quot;;  &lt;br /&gt;  // rewrite the URL&lt;br /&gt;  Context.RewritePath( strCustomPath );&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;As you can see from the code above, the URL Redirection is only limited to one rules. It will always redirect to one page called product10.aspx if it detects that your URL contains ID keyword.&lt;br /&gt;Of course this one will not work if you want different Query String ID to redirect to different page or if you want to have different page redirection for different query string type.&lt;br /&gt;&lt;br /&gt;To have a more complex URL Rewriting Rules, we can use Regular Expressions for implementing different redirection techniques.&lt;br /&gt;&lt;br /&gt;Now, lets start writing some rules for your Redirection.&lt;br /&gt;&lt;br /&gt;&lt;urlrewrites&gt;&lt;br /&gt; &lt;rule&gt;&lt;br /&gt;  &lt;url&gt;product/(.*)\.aspx&lt;/url&gt;&lt;br /&gt;  &lt;rewrite&gt;displayProduct.aspx?ID=$1&lt;/rewrite&gt;&lt;br /&gt; &lt;/rule&gt;&lt;br /&gt;        &lt;rule&gt;&lt;br /&gt;  &lt;url&gt;Items/Mouse/(.*)\.aspx&lt;/url&gt;&lt;br /&gt;  &lt;rewrite&gt;ViewItem.aspx?ID=$1&lt;/rewrite&gt;&lt;br /&gt; &lt;/rule&gt;&lt;br /&gt;&lt;br /&gt;&lt;/urlrewrites&gt;&lt;br /&gt;&lt;br /&gt;As you can see from the first rules above, It will redirect the URL from product/(Number).aspx into displayProduct.aspx?ID=(Number).&lt;br /&gt;Second rules will redirect the URL if it Contains Items/Mouse/(Number).aspx into ViewItem.aspx?ID=(Number). You can add as many rules as you like by just adding the xml node above&lt;br /&gt;&lt;br /&gt;   void Application_BeginRequest(Object sender, EventArgs e)&lt;br /&gt;    {&lt;br /&gt;        string sPath = Context.Request.Path;        &lt;br /&gt;        //To overcome Postback issues, stored the real URL.&lt;br /&gt;        Context.Items[&quot;VirtualURL&quot;] = sPath;&lt;br /&gt;        Regex oReg;&lt;br /&gt;        XmlDocument xmlDoc = new XmlDocument();&lt;br /&gt;        xmlDoc.Load(Server.MapPath(&quot;/XML/Rule.xml&quot;));&lt;br /&gt;        _oRules = xmlDoc.DocumentElement;&lt;br /&gt;&lt;br /&gt;        foreach (XmlNode oNode in _oRules.SelectNodes(&quot;rule&quot;))&lt;br /&gt;        {&lt;br /&gt;            oReg = new Regex(oNode.SelectSingleNode(&quot;url/text()&quot;).Value);&lt;br /&gt;            Match oMatch = oReg.Match(sPath);&lt;br /&gt;&lt;br /&gt;            if (oMatch.Success)&lt;br /&gt;            {&lt;br /&gt;                sPath = oReg.Replace(sPath, oNode.SelectSingleNode(&quot;rewrite/text()&quot;).Value);&lt;br /&gt;                break;&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;        Context.RewritePath(sPath);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;The code above is self explanatory. It will search from the rules in XML file and if it match, then it will rewrite the path.&lt;br /&gt;Thats all you need to do to implement URL Rewriting. However after you rewrite the URL, all your page postbacks will not work.  The reason is because, ASP.NET will automatically by default output the &quot;action&quot; attribute of the markup to point back to the page it is on. The problem when using URL-Rewriting is that the URL that the page renders is not the original URL of the request . This means that when you do a postback to the server, the URL will not be your nice clean one.&lt;br /&gt;&lt;br /&gt;To overcome this problem, you need to add this code on every page that you want to do postbacks.&lt;br /&gt;&lt;br /&gt;    protected override void Render(HtmlTextWriter writer)&lt;br /&gt;    {&lt;br /&gt;        if (HttpContext.Current.Items[&quot;VirtualURL&quot;] != null)&lt;br /&gt;        {&lt;br /&gt;            string sVirURL= HttpContext.Current.Items[&quot;VirtualURL&quot;].ToString()&lt;br /&gt;            RewriteFormHtmlTextWriter oWriter = new RewriteFormHtmlTextWriter(writer,sVirURL);&lt;br /&gt;            base.Render(oWriter);&lt;br /&gt;        }&lt;br /&gt;        &lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;Source Code for RewriteFormHtmlTextWriter&lt;br /&gt;&lt;br /&gt;public class RewriteFormHtmlTextWriter : HtmlTextWriter&lt;br /&gt;{&lt;br /&gt;    private bool inForm;&lt;br /&gt;    private string _formAction;&lt;br /&gt;&lt;br /&gt;    public RewriteFormHtmlTextWriter(System.IO.TextWriter writer):base(writer)&lt;br /&gt;    {&lt;br /&gt;&lt;br /&gt;    }&lt;br /&gt;    public override void RenderBeginTag(string tagName)&lt;br /&gt;    {&lt;br /&gt;        if (tagName.ToString().IndexOf(&quot;form&quot;) &gt;= 0)&lt;br /&gt;        {&lt;br /&gt;            base.RenderBeginTag(tagName);&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;    public RewriteFormHtmlTextWriter(System.IO.TextWriter writer, string action)&lt;br /&gt;        : base(writer)&lt;br /&gt;    {&lt;br /&gt;&lt;br /&gt;        this._formAction = action;&lt;br /&gt;&lt;br /&gt;    }&lt;br /&gt;    public override void WriteAttribute(string name, string value, bool fEncode)&lt;br /&gt;    {&lt;br /&gt;        if (name == &quot;action&quot;)&lt;br /&gt;        {&lt;br /&gt;            value = _formAction;&lt;br /&gt;        }&lt;br /&gt;        base.WriteAttribute(name, value, fEncode);&lt;br /&gt;    }&lt;br /&gt;   &lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;That&#39;s all you need to implement a complex and fully extensible URL Rewriting. You can create unlimited rules into your Rules.xml file and redirect to the page you want.&lt;br /&gt;&lt;br /&gt;Conclusion&lt;br /&gt;&lt;br /&gt;In this article, you can see how easy it is to implement URL Rewriting for your website. You can do enhancements and improve the workflow of the code above. For faster execution of your rules, you can also stores the Rules.xml files as Caching objects so it will save lots of time compare to open and close the xml files everytime the rewrite happens.&lt;div class=&quot;blogger-post-footer&quot;&gt;octopus east java baker&lt;/div&gt;</description><link>http://scriptster.blogspot.com/2007/11/url-rewriting-with-aspnet-20.html</link><author>noreply@blogger.com (Octopus)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-2977499297091575918.post-3405538963552959043</guid><pubDate>Wed, 24 Oct 2007 09:08:00 +0000</pubDate><atom:updated>2007-10-24T02:08:52.722-07:00</atom:updated><title>Storing Images in database with C#</title><description>&lt;span id=&quot;intelliTXT&quot;&gt;&lt;h2&gt;Storing Images&lt;/h2&gt; &lt;ol&gt;&lt;li&gt;Create a table in a SQL Server 2000 database which has at least one field of type &lt;code&gt;IMAGE&lt;/code&gt;.  &lt;p&gt;Here is the script I used:&lt;/p&gt;&lt;pre lang=&quot;sql&quot;&gt;&lt;span class=&quot;vb-function&quot;&gt;CREATE&lt;/span&gt; &lt;span class=&quot;vb-function&quot;&gt;TABLE&lt;/span&gt; [dbo].[tblImgData] (&lt;br /&gt;&lt;br /&gt;       [ID] [&lt;span class=&quot;cpp-keyword&quot;&gt;int&lt;/span&gt;] &lt;span class=&quot;vb-function&quot;&gt;NOT&lt;/span&gt; &lt;span class=&quot;vb-function&quot;&gt;NULL&lt;/span&gt; ,&lt;br /&gt;&lt;br /&gt;       [Name] [&lt;span class=&quot;cpp-keyword&quot;&gt;varchar&lt;/span&gt;] (&lt;span class=&quot;vb-literal&quot;&gt;50&lt;/span&gt;) &lt;span class=&quot;vb-function&quot;&gt;COLLATE&lt;/span&gt; SQL_Latin1_General_CP1_CI_AS &lt;span class=&quot;vb-function&quot;&gt;NULL&lt;/span&gt; ,&lt;br /&gt;&lt;br /&gt;       [Picture] [&lt;span class=&quot;cpp-keyword&quot;&gt;image&lt;/span&gt;] &lt;span class=&quot;vb-function&quot;&gt;NULL&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;) &lt;span class=&quot;vb-function&quot;&gt;ON&lt;/span&gt; [&lt;span class=&quot;vb-function&quot;&gt;PRIMARY&lt;/span&gt;] TEXTIMAGE_ON [&lt;span class=&quot;vb-function&quot;&gt;PRIMARY&lt;/span&gt;]&lt;/pre&gt; &lt;/li&gt;&lt;li&gt;Actually &lt;code&gt;IMAGE&lt;/code&gt; field is just holding the reference to the page containing the binary data so we have to convert our image into bytes.  &lt;ol type=&quot;a&quot;&gt;&lt;li&gt;I used a file open dialog box to locate the file. &lt;pre lang=&quot;cs&quot;&gt;&lt;span class=&quot;cs-keyword&quot;&gt;this&lt;/span&gt;.openFileDialog1.ShowDialog(&lt;span class=&quot;cs-keyword&quot;&gt;this&lt;/span&gt;);&lt;br /&gt;&lt;span class=&quot;cs-keyword&quot;&gt;string&lt;/span&gt; strFn=&lt;span class=&quot;cs-keyword&quot;&gt;this&lt;/span&gt;.openFileDialog1.FileName;&lt;/pre&gt; &lt;/li&gt;&lt;li&gt;By using &lt;code&gt;FileInfo&lt;/code&gt; class, I retrieved the file size: &lt;pre lang=&quot;cs&quot;&gt;FileInfo fiImage=&lt;span class=&quot;cs-keyword&quot;&gt;new&lt;/span&gt; FileInfo(strFn);&lt;/pre&gt; &lt;/li&gt;&lt;li&gt;Declare an array of that size. &lt;pre lang=&quot;cs&quot;&gt;&lt;span class=&quot;cs-keyword&quot;&gt;this&lt;/span&gt;.m_lImageFileLength=fiImage.Length;&lt;br /&gt;m_barrImg=&lt;span class=&quot;cs-keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;cs-keyword&quot;&gt;byte&lt;/span&gt;[Convert.ToInt32(&lt;span class=&quot;cs-keyword&quot;&gt;this&lt;/span&gt;.m_lImageFileLength)];&lt;/pre&gt; &lt;/li&gt;&lt;li&gt;By using &lt;code&gt;FileStream&lt;/code&gt; object, I filled the byte array. &lt;pre lang=&quot;cs&quot;&gt;FileStream fs=&lt;span class=&quot;cs-keyword&quot;&gt;new&lt;/span&gt; FileStream(strFn,FileMode.Open,&lt;br /&gt;                 FileAccess.Read,FileShare.Read);&lt;br /&gt;&lt;span class=&quot;cs-keyword&quot;&gt;int&lt;/span&gt; iBytesRead=fs.Read(m_barrImg,&lt;span class=&quot;cs-literal&quot;&gt;0&lt;/span&gt;,&lt;br /&gt;              Convert.ToInt32(&lt;span class=&quot;cs-keyword&quot;&gt;this&lt;/span&gt;.m_lImageFileLength));&lt;br /&gt;fs.Close();&lt;/pre&gt;&lt;/li&gt;&lt;/ol&gt; &lt;h3&gt;Complete Load Image Code&lt;/h3&gt;&lt;pre lang=&quot;cs&quot;&gt;&lt;span class=&quot;cs-keyword&quot;&gt;protected&lt;/span&gt; &lt;span class=&quot;cs-keyword&quot;&gt;void&lt;/span&gt; LoadImage()&lt;br /&gt;{&lt;br /&gt;   &lt;span class=&quot;cs-keyword&quot;&gt;try&lt;/span&gt;&lt;br /&gt;   {&lt;br /&gt;       &lt;span class=&quot;cs-keyword&quot;&gt;this&lt;/span&gt;.openFileDialog1.ShowDialog(&lt;span class=&quot;cs-keyword&quot;&gt;this&lt;/span&gt;);&lt;br /&gt;       &lt;span class=&quot;cs-keyword&quot;&gt;string&lt;/span&gt; strFn=&lt;span class=&quot;cs-keyword&quot;&gt;this&lt;/span&gt;.openFileDialog1.FileName;&lt;br /&gt;       &lt;span class=&quot;cs-keyword&quot;&gt;this&lt;/span&gt;.pictureBox1.Image=Image.FromFile(strFn);&lt;br /&gt;       FileInfo fiImage=&lt;span class=&quot;cs-keyword&quot;&gt;new&lt;/span&gt; FileInfo(strFn);&lt;br /&gt;       &lt;span class=&quot;cs-keyword&quot;&gt;this&lt;/span&gt;.m_lImageFileLength=fiImage.Length;&lt;br /&gt;       FileStream fs=&lt;span class=&quot;cs-keyword&quot;&gt;new&lt;/span&gt; FileStream(strFn,FileMode.Open,&lt;br /&gt;                         FileAccess.Read,FileShare.Read);&lt;br /&gt;       m_barrImg=&lt;span class=&quot;cs-keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;cs-keyword&quot;&gt;byte&lt;/span&gt;[Convert.ToInt32(&lt;span class=&quot;cs-keyword&quot;&gt;this&lt;/span&gt;.m_lImageFileLength)];&lt;br /&gt;       &lt;span class=&quot;cs-keyword&quot;&gt;int&lt;/span&gt; iBytesRead = fs.Read(m_barrImg,&lt;span class=&quot;cs-literal&quot;&gt;0&lt;/span&gt;,&lt;br /&gt;                        Convert.ToInt32(&lt;span class=&quot;cs-keyword&quot;&gt;this&lt;/span&gt;.m_lImageFileLength));&lt;br /&gt;       fs.Close();&lt;br /&gt;   }&lt;br /&gt;   &lt;span class=&quot;cs-keyword&quot;&gt;catch&lt;/span&gt;(Exception ex)&lt;br /&gt;   {&lt;br /&gt;       MessageBox.Show(ex.Message);&lt;br /&gt;   }&lt;br /&gt;}&lt;/pre&gt; &lt;/li&gt;&lt;li&gt;Saving byte array data to database.  &lt;ol type=&quot;a&quot;&gt;&lt;li&gt;Create command text to insert record. &lt;pre lang=&quot;cs&quot;&gt;&lt;span class=&quot;cs-keyword&quot;&gt;this&lt;/span&gt;.sqlCommand1.CommandText=&lt;br /&gt; &lt;span class=&quot;cpp-string&quot;&gt;&quot;INSERT INTO tblImgData(ID,Name,Picture)&quot;&lt;/span&gt; +&lt;br /&gt; &lt;span class=&quot;cpp-string&quot;&gt;&quot; values(@ID,@Name,@Picture)&quot;&lt;/span&gt;;&lt;/pre&gt; &lt;/li&gt;&lt;li&gt;Create parameters. &lt;pre lang=&quot;cs&quot;&gt;&lt;span class=&quot;cs-keyword&quot;&gt;this&lt;/span&gt;.sqlCommand1.Parameters.Add(&lt;span class=&quot;cpp-string&quot;&gt;&quot;@ID&quot;&lt;/span&gt;,&lt;br /&gt;          System.Data.SqlDbType.Int, &lt;span class=&quot;cs-literal&quot;&gt;4&lt;/span&gt;);&lt;br /&gt;&lt;span class=&quot;cs-keyword&quot;&gt;this&lt;/span&gt;.sqlCommand1.Parameters.Add(&lt;span class=&quot;cpp-string&quot;&gt;&quot;@Name&quot;&lt;/span&gt;,&lt;br /&gt;          System.Data.SqlDbType.VarChar, &lt;span class=&quot;cs-literal&quot;&gt;50&lt;/span&gt;);&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;cs-keyword&quot;&gt;this&lt;/span&gt;.sqlCommand1.Parameters.Add(&lt;span class=&quot;cpp-string&quot;&gt;&quot;@Picture&quot;&lt;/span&gt;,&lt;br /&gt;          System.Data.SqlDbType.Image);&lt;/pre&gt; &lt;p&gt;Notice “&lt;code&gt;@Picture&lt;/code&gt;” has “&lt;code&gt;SqlDbType.Image&lt;/code&gt;” because it is of &lt;code&gt;IMAGE&lt;/code&gt; type Field.&lt;/p&gt; &lt;/li&gt;&lt;li&gt;Provide the value to the parameters. &lt;pre lang=&quot;cs&quot;&gt;&lt;span class=&quot;cs-keyword&quot;&gt;this&lt;/span&gt;.sqlCommand1.Parameters[&lt;span class=&quot;cpp-string&quot;&gt;&quot;@ID&quot;&lt;/span&gt;].Value=&lt;span class=&quot;cs-keyword&quot;&gt;this&lt;/span&gt;.editID.Text;&lt;br /&gt;&lt;span class=&quot;cs-keyword&quot;&gt;this&lt;/span&gt;.sqlCommand1.Parameters[&lt;span class=&quot;cpp-string&quot;&gt;&quot;@Name&quot;&lt;/span&gt;].Value=&lt;span class=&quot;cs-keyword&quot;&gt;this&lt;/span&gt;.editName.Text;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;cs-keyword&quot;&gt;this&lt;/span&gt;.sqlCommand1.Parameters[&lt;span class=&quot;cpp-string&quot;&gt;&quot;@Picture&quot;&lt;/span&gt;].Value=&lt;span class=&quot;cs-keyword&quot;&gt;this&lt;/span&gt;.m_barrImg;&lt;/pre&gt; &lt;p&gt;“&lt;code lang=&quot;cs&quot;&gt;&lt;span class=&quot;cs-keyword&quot;&gt;this&lt;/span&gt;.m_barrImg&lt;/code&gt;” is a byte array which we filled in the previous step.&lt;/p&gt; &lt;/li&gt;&lt;li&gt;Now execute non-query for saving the record to the database. &lt;pre lang=&quot;cs&quot;&gt;&lt;span class=&quot;cs-keyword&quot;&gt;int&lt;/span&gt; iresult=&lt;span class=&quot;cs-keyword&quot;&gt;this&lt;/span&gt;.sqlCommand1.ExecuteNonQuery();&lt;/pre&gt;&lt;/li&gt;&lt;/ol&gt; &lt;h3&gt;Complete Save Image Code&lt;/h3&gt;&lt;div class=&quot;smallText&quot; id=&quot;premain10&quot; style=&quot;width: 100%;&quot;&gt;&lt;img preid=&quot;10&quot; src=&quot;http://www.codeproject.com/images/minus.gif&quot; id=&quot;preimg10&quot; height=&quot;9&quot; width=&quot;9&quot; /&gt;&lt;span preid=&quot;10&quot; style=&quot;margin-bottom: 0pt;&quot; id=&quot;precollapse10&quot;&gt; Collapse&lt;/span&gt;&lt;/div&gt;&lt;pre style=&quot;margin-top: 0pt;&quot; id=&quot;pre10&quot; lang=&quot;cs&quot;&gt;&lt;span class=&quot;cs-keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;cs-keyword&quot;&gt;void&lt;/span&gt; btnSave_Click(&lt;span class=&quot;cs-keyword&quot;&gt;object&lt;/span&gt; sender, System.EventArgs e)&lt;br /&gt;{&lt;br /&gt;   &lt;span class=&quot;cs-keyword&quot;&gt;try&lt;/span&gt;&lt;br /&gt;   {&lt;br /&gt;       &lt;span class=&quot;cs-keyword&quot;&gt;this&lt;/span&gt;.sqlConnection1.Open();&lt;br /&gt;       &lt;span class=&quot;cs-keyword&quot;&gt;if&lt;/span&gt; (sqlCommand1.Parameters.Count ==&lt;span class=&quot;cs-literal&quot;&gt;0&lt;/span&gt; )&lt;br /&gt;       {&lt;br /&gt;           &lt;span class=&quot;cs-keyword&quot;&gt;this&lt;/span&gt;.sqlCommand1.CommandText=&lt;span class=&quot;cpp-string&quot;&gt;&quot;INSERT INTO tblImgData(ID,&quot;&lt;/span&gt; +&lt;br /&gt;                          &lt;span class=&quot;cpp-string&quot;&gt;&quot; Name,Picture) values(@ID,@Name,@Picture)&quot;&lt;/span&gt;;&lt;br /&gt;           &lt;span class=&quot;cs-keyword&quot;&gt;this&lt;/span&gt;.sqlCommand1.Parameters.Add(&lt;span class=&quot;cpp-string&quot;&gt;&quot;@ID&quot;&lt;/span&gt;,&lt;br /&gt;                            System.Data.SqlDbType.Int,&lt;span class=&quot;cs-literal&quot;&gt;4&lt;/span&gt;);&lt;br /&gt;           &lt;span class=&quot;cs-keyword&quot;&gt;this&lt;/span&gt;.sqlCommand1.Parameters.Add(&lt;span class=&quot;cpp-string&quot;&gt;&quot;@Name&quot;&lt;/span&gt;,&lt;br /&gt;                            System.Data.SqlDbType.VarChar,&lt;span class=&quot;cs-literal&quot;&gt;50&lt;/span&gt;);&lt;br /&gt;           &lt;span class=&quot;cs-keyword&quot;&gt;this&lt;/span&gt;.sqlCommand1.Parameters.Add(&lt;span class=&quot;cpp-string&quot;&gt;&quot;@Picture&quot;&lt;/span&gt;,&lt;br /&gt;                            System.Data.SqlDbType.Image);&lt;br /&gt;       }&lt;br /&gt;&lt;br /&gt;       &lt;span class=&quot;cs-keyword&quot;&gt;this&lt;/span&gt;.sqlCommand1.Parameters[&lt;span class=&quot;cpp-string&quot;&gt;&quot;@ID&quot;&lt;/span&gt;].Value=&lt;span class=&quot;cs-keyword&quot;&gt;this&lt;/span&gt;.editID.Text;&lt;br /&gt;       &lt;span class=&quot;cs-keyword&quot;&gt;this&lt;/span&gt;.sqlCommand1.Parameters[&lt;span class=&quot;cpp-string&quot;&gt;&quot;@Name&quot;&lt;/span&gt;].Value=&lt;span class=&quot;cs-keyword&quot;&gt;this&lt;/span&gt;.editName.Text;&lt;br /&gt;       &lt;span class=&quot;cs-keyword&quot;&gt;this&lt;/span&gt;.sqlCommand1.Parameters[&lt;span class=&quot;cpp-string&quot;&gt;&quot;@Picture&quot;&lt;/span&gt;].Value=&lt;span class=&quot;cs-keyword&quot;&gt;this&lt;/span&gt;.m_barrImg;&lt;br /&gt;&lt;br /&gt;       &lt;span class=&quot;cs-keyword&quot;&gt;int&lt;/span&gt; iresult=&lt;span class=&quot;cs-keyword&quot;&gt;this&lt;/span&gt;.sqlCommand1.ExecuteNonQuery();&lt;br /&gt;       MessageBox.Show(Convert.ToString(iresult));&lt;br /&gt;   }&lt;br /&gt;   &lt;span class=&quot;cs-keyword&quot;&gt;catch&lt;/span&gt;(Exception ex)&lt;br /&gt;   {&lt;br /&gt;       MessageBox.Show(ex.Message);&lt;br /&gt;   }&lt;br /&gt;   &lt;span class=&quot;cs-keyword&quot;&gt;finally&lt;/span&gt;&lt;br /&gt;   {&lt;br /&gt;       &lt;span class=&quot;cs-keyword&quot;&gt;this&lt;/span&gt;.sqlConnection1.Close();&lt;br /&gt;   }&lt;br /&gt;}&lt;/pre&gt;&lt;/li&gt;&lt;/ol&gt; &lt;h2&gt;Retrieving Image&lt;/h2&gt; &lt;p&gt;Retrieving images from the database is the exact reverse process of saving images to the database.&lt;/p&gt; &lt;ol&gt;&lt;li&gt;First create command text to retrieve record. &lt;pre lang=&quot;cs&quot;&gt;SqlCommand cmdSelect = &lt;span class=&quot;cs-keyword&quot;&gt;new&lt;/span&gt; SqlCommand(&lt;span class=&quot;cpp-string&quot;&gt;&quot;select Picture&quot;&lt;/span&gt; +&lt;br /&gt;                      &lt;span class=&quot;cpp-string&quot;&gt;&quot; from tblImgData where ID=@ID&quot;&lt;/span&gt;,&lt;br /&gt;                      &lt;span class=&quot;cs-keyword&quot;&gt;this&lt;/span&gt;.sqlConnection1);&lt;/pre&gt; &lt;/li&gt;&lt;li&gt;Create parameter for the query. &lt;pre lang=&quot;cs&quot;&gt;cmdSelect.Parameters.Add(&lt;span class=&quot;cpp-string&quot;&gt;&quot;@ID&quot;&lt;/span&gt;,SqlDbType.Int,&lt;span class=&quot;cs-literal&quot;&gt;4&lt;/span&gt;);&lt;/pre&gt; &lt;/li&gt;&lt;li&gt;Provide value to the parameter. &lt;pre lang=&quot;cs&quot;&gt;cmdSelect.Parameters[&lt;span class=&quot;cpp-string&quot;&gt;&quot;@ID&quot;&lt;/span&gt;].Value=&lt;span class=&quot;cs-keyword&quot;&gt;this&lt;/span&gt;.editID.Text;&lt;/pre&gt; &lt;/li&gt;&lt;li&gt;Open database connection and execute “&lt;code&gt;ExecuteScalar&lt;/code&gt;” because we want only “&lt;code&gt;IMAGE&lt;/code&gt;” column data back. &lt;pre lang=&quot;cs&quot;&gt;&lt;span class=&quot;cs-keyword&quot;&gt;byte&lt;/span&gt;[] barrImg=(&lt;span class=&quot;cs-keyword&quot;&gt;byte&lt;/span&gt;[])cmdSelect.ExecuteScalar();&lt;/pre&gt; &lt;p&gt;As the execute scalar returns data of “&lt;code lang=&quot;cs&quot;&gt;Object&lt;/code&gt;” data type, we cast it to &lt;code lang=&quot;cs&quot;&gt;&lt;span class=&quot;cs-keyword&quot;&gt;byte&lt;/span&gt;&lt;/code&gt; array.&lt;/p&gt; &lt;/li&gt;&lt;li&gt;Save this data to a temporary file. &lt;pre lang=&quot;cs&quot;&gt;&lt;span class=&quot;cs-keyword&quot;&gt;string&lt;/span&gt; strfn=Convert.ToString(DateTime.Now.ToFileTime());&lt;br /&gt;FileStream fs=&lt;span class=&quot;cs-keyword&quot;&gt;new&lt;/span&gt; FileStream(strfn,FileMode.CreateNew,FileAccess.Write);&lt;br /&gt;fs.Write(barrImg,&lt;span class=&quot;cs-literal&quot;&gt;0&lt;/span&gt;,barrImg.Length);&lt;br /&gt;fs.Flush();&lt;br /&gt;fs.Close();&lt;/pre&gt; &lt;/li&gt;&lt;li&gt;And display the image anywhere you want to display. &lt;pre lang=&quot;cs&quot;&gt;pictureBox1.Image=Image.FromFile(strfn);&lt;/pre&gt;&lt;/li&gt;&lt;/ol&gt; &lt;h3&gt;Complete Image Retrieving Code&lt;/h3&gt;&lt;pre lang=&quot;cs&quot;&gt;&lt;span class=&quot;cs-keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;cs-keyword&quot;&gt;void&lt;/span&gt; btnLoad_Click(&lt;span class=&quot;cs-keyword&quot;&gt;object&lt;/span&gt; sender, System.EventArgs e)&lt;br /&gt;{&lt;br /&gt;   &lt;span class=&quot;cs-keyword&quot;&gt;try&lt;/span&gt;&lt;br /&gt;   {&lt;br /&gt;       SqlCommand cmdSelect=&lt;span class=&quot;cs-keyword&quot;&gt;new&lt;/span&gt; SqlCommand(&lt;span class=&quot;cpp-string&quot;&gt;&quot;select Picture&quot;&lt;/span&gt; +&lt;br /&gt;             &lt;span class=&quot;cpp-string&quot;&gt;&quot; from tblImgData where ID=@ID&quot;&lt;/span&gt;,&lt;span class=&quot;cs-keyword&quot;&gt;this&lt;/span&gt;.sqlConnection1);&lt;br /&gt;       cmdSelect.Parameters.Add(&lt;span class=&quot;cpp-string&quot;&gt;&quot;@ID&quot;&lt;/span&gt;,SqlDbType.Int,&lt;span class=&quot;cs-literal&quot;&gt;4&lt;/span&gt;);&lt;br /&gt;       cmdSelect.Parameters[&lt;span class=&quot;cpp-string&quot;&gt;&quot;@ID&quot;&lt;/span&gt;].Value=&lt;span class=&quot;cs-keyword&quot;&gt;this&lt;/span&gt;.editID.Text;&lt;br /&gt;&lt;br /&gt;       &lt;span class=&quot;cs-keyword&quot;&gt;this&lt;/span&gt;.sqlConnection1.Open();&lt;br /&gt;       &lt;span class=&quot;cs-keyword&quot;&gt;byte&lt;/span&gt;[] barrImg=(&lt;span class=&quot;cs-keyword&quot;&gt;byte&lt;/span&gt;[])cmdSelect.ExecuteScalar();&lt;br /&gt;       &lt;span class=&quot;cs-keyword&quot;&gt;string&lt;/span&gt; strfn=Convert.ToString(DateTime.Now.ToFileTime());&lt;br /&gt;       FileStream fs=&lt;span class=&quot;cs-keyword&quot;&gt;new&lt;/span&gt; FileStream(strfn,&lt;br /&gt;                         FileMode.CreateNew, FileAccess.Write);&lt;br /&gt;       fs.Write(barrImg,&lt;span class=&quot;cs-literal&quot;&gt;0&lt;/span&gt;,barrImg.Length);&lt;br /&gt;       fs.Flush();&lt;br /&gt;       fs.Close();&lt;br /&gt;       pictureBox1.Image=Image.FromFile(strfn);&lt;br /&gt;   }&lt;br /&gt;   &lt;span class=&quot;cs-keyword&quot;&gt;catch&lt;/span&gt;(Exception ex)&lt;br /&gt;   {&lt;br /&gt;       MessageBox.Show(ex.Message);&lt;br /&gt;   }&lt;br /&gt;   &lt;span class=&quot;cs-keyword&quot;&gt;finally&lt;/span&gt;&lt;br /&gt;   {&lt;br /&gt;       &lt;span class=&quot;cs-keyword&quot;&gt;this&lt;/span&gt;.sqlConnection1.Close();&lt;br /&gt;   }&lt;br /&gt;}&lt;/pre&gt;&lt;/span&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;octopus east java baker&lt;/div&gt;</description><link>http://scriptster.blogspot.com/2007/10/storing-images-in-database-with-c.html</link><author>noreply@blogger.com (Octopus)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-2977499297091575918.post-7857182072207030602</guid><pubDate>Wed, 24 Oct 2007 09:06:00 +0000</pubDate><atom:updated>2007-10-24T02:07:24.958-07:00</atom:updated><title>Storing Binary Data to Database using ASP.NET 2.0</title><description>&lt;p class=&quot;ArticleText&quot;&gt;As a developer, you might face few requirements where you want to upload large documents, PDF&#39;s and images from your application. Then how do you manage and store such large data? Usually, traditional approach was to store those large files on web server&#39;s file system. But you also have database approach which allows you to store those large documents like PDF&#39;s, .zip files, images etc., as binary data directly in the database itself. Let&#39;s elaborate on Database approach a bit further. How do we usually store large data objects in Databases like SQL Server 2000? Ok, SQL server 2000 supports exclusive image data type to hold image data. Now SQL Server 2005 supports another new data type varbinary which allows storing binary data up to 2GB in size.&lt;/p&gt; &lt;p class=&quot;ArticleText&quot;&gt;Even with new data types, we still need to understand that working with binary data is not the same as straight forward working with text data. So, we are here to discuss how to use ASP.NET 2.0 SqlDataSource control to store and retrieve image files directly from a database.&lt;/p&gt; &lt;p class=&quot;ArticleText&quot;&gt;We will create application which allows user to upload images and display the uploaded pictures.  The uploaded images will be stored in database as binary data. You can &lt;a href=&quot;http://www.beansoftware.com/ASP.NET-Tutorials/Examples/Binary-Data.zip&quot;&gt;download sample project&lt;/a&gt;, used in this tutorial.  To hold image data, we need to create new table called PictureTable as shown below&lt;/p&gt; &lt;div align=&quot;center&quot;&gt;&lt;img src=&quot;http://www.beansoftware.com/ASP.NET-Tutorials/Images/Binary-Data-Database.jpg&quot; /&gt;&lt;/div&gt; &lt;p class=&quot;ArticleText&quot;&gt;&lt;span style=&quot;color:blue;&quot;&gt;if&lt;/span&gt; &lt;span style=&quot;color:blue;&quot;&gt;exists&lt;/span&gt; (&lt;span style=&quot;color:blue;&quot;&gt;select&lt;/span&gt; * &lt;span style=&quot;color:blue;&quot;&gt;from&lt;/span&gt; dbo.sysobjects &lt;span style=&quot;color:blue;&quot;&gt;where&lt;/span&gt; id = object_id(N&#39;[dbo].[PictureTable]&#39;) &lt;span style=&quot;color:blue;&quot;&gt;and&lt;/span&gt; OBJECTPROPERTY(id, N&#39;IsUserTable&#39;) = 1)&lt;br /&gt;&lt;span style=&quot;color:blue;&quot;&gt;drop&lt;/span&gt; &lt;span style=&quot;color:blue;&quot;&gt;table&lt;/span&gt; [dbo].[PictureTable]&lt;br /&gt;GO&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color:blue;&quot;&gt;CREATE&lt;/span&gt; &lt;span style=&quot;color:blue;&quot;&gt;TABLE&lt;/span&gt; [dbo].[PictureTable] (&lt;br /&gt;   [ImageID] [int] &lt;span style=&quot;color:blue;&quot;&gt;IDENTITY&lt;/span&gt; (1, 1) &lt;span style=&quot;color:blue;&quot;&gt;NOT&lt;/span&gt; NULL ,&lt;br /&gt;   [Title] [varchar] (50) &lt;span style=&quot;color:blue;&quot;&gt;COLLATE&lt;/span&gt; SQL_Latin1_General_CP1_CI_AS &lt;span style=&quot;color:blue;&quot;&gt;NOT&lt;/span&gt; NULL ,&lt;br /&gt;   [DateAdded] [datetime] &lt;span style=&quot;color:blue;&quot;&gt;NOT&lt;/span&gt; NULL ,&lt;br /&gt;   [MIMEType] [varchar] (50) &lt;span style=&quot;color:blue;&quot;&gt;COLLATE&lt;/span&gt; SQL_Latin1_General_CP1_CI_AS &lt;span style=&quot;color:blue;&quot;&gt;NOT&lt;/span&gt; NULL ,&lt;br /&gt;   [Image] [image] &lt;span style=&quot;color:blue;&quot;&gt;NOT&lt;/span&gt; NULL  &lt;br /&gt;) &lt;span style=&quot;color:blue;&quot;&gt;ON&lt;/span&gt; [&lt;span style=&quot;color:blue;&quot;&gt;PRIMARY&lt;/span&gt;] TEXTIMAGE_ON [&lt;span style=&quot;color:blue;&quot;&gt;PRIMARY&lt;/span&gt;]&lt;br /&gt;GO&lt;br /&gt;&lt;i&gt;Schema script for PictureTable&lt;/i&gt;&lt;/p&gt; &lt;p class=&quot;ArticleText&quot;&gt;This table records details of pictures and content. The PictureTable table&#39;s MIMEType field holds the MIME type of the uploaded image (image/jpeg for JPG files, image/gif for GIF files, and so on); the MIME type specifies to the browser how to render the binary data. The Image column holds the actual binary contents of the picture.&lt;/p&gt; &lt;p class=&quot;ArticleText&quot;&gt;&lt;span style=&quot;color:blue;&quot;&gt; &lt;&lt;/span&gt;&lt;span style=&quot;color:maroon;&quot;&gt;asp&lt;/span&gt;&lt;span style=&quot;color:blue;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:maroon;&quot;&gt;Label&lt;/span&gt;&lt;span&gt; &lt;span style=&quot;color:red;&quot;&gt;ID&lt;/span&gt;&lt;span style=&quot;color:blue;&quot;&gt;=&quot;Label1&quot;&lt;/span&gt;  &lt;span style=&quot;color:red;&quot;&gt;runat&lt;/span&gt;&lt;span style=&quot;color:blue;&quot;&gt;=&quot;server&quot;&lt;/span&gt; &lt;span style=&quot;color:red;&quot;&gt;Text&lt;/span&gt;&lt;span style=&quot;color:blue;&quot;&gt;=&quot;Upload Image&quot;&lt;!--&lt;/span--&gt;&lt;span style=&quot;color:maroon;&quot;&gt;asp&lt;/span&gt;&lt;span style=&quot;color:blue;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:maroon;&quot;&gt;Label&lt;/span&gt;&lt;span style=&quot;color:blue;&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color:maroon;&quot;&gt; &lt;asp&gt;&lt;/asp&gt;&lt;/span&gt;&lt;span style=&quot;color:blue;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:maroon;&quot;&gt;Label&lt;/span&gt;&lt;span&gt; &lt;span style=&quot;color:red;&quot;&gt;ID&lt;/span&gt;&lt;span style=&quot;color:blue;&quot;&gt;=&quot;Label2&quot;&lt;/span&gt; &lt;span style=&quot;color:red;&quot;&gt;runat&lt;/span&gt;&lt;span style=&quot;color:blue;&quot;&gt;=&quot;server&quot;&lt;/span&gt; &lt;span style=&quot;color:red;&quot;&gt;Text&lt;/span&gt;&lt;span style=&quot;color:blue;&quot;&gt;=&quot;Title&quot;&gt;&lt;!--&lt;/span--&gt;&lt;span style=&quot;color:maroon;&quot;&gt;asp&lt;/span&gt;&lt;span style=&quot;color:blue;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:maroon;&quot;&gt;Label&lt;/span&gt;&lt;span style=&quot;color:blue;&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt; &lt;span style=&quot;color:blue;&quot;&gt;&lt;&lt;/span&gt;&lt;span style=&quot;color:maroon;&quot;&gt;asp&lt;/span&gt;&lt;span style=&quot;color:blue;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:maroon;&quot;&gt;TextBox&lt;/span&gt; &lt;span style=&quot;color:red;&quot;&gt;ID&lt;/span&gt;&lt;span style=&quot;color:blue;&quot;&gt;=&quot;TextBox1&quot;&lt;/span&gt; &lt;span style=&quot;color:red;&quot;&gt;runat&lt;/span&gt;&lt;span style=&quot;color:blue;&quot;&gt;=&quot;server&quot;&gt;&lt;!--&lt;/span--&gt;&lt;span style=&quot;color:maroon;&quot;&gt;asp&lt;/span&gt;&lt;span style=&quot;color:blue;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:maroon;&quot;&gt;TextBox&lt;/span&gt;&lt;span style=&quot;color:blue;&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt; &lt;span style=&quot;color:blue;&quot;&gt;&lt;&lt;/span&gt;&lt;span style=&quot;color:maroon;&quot;&gt;asp&lt;/span&gt;&lt;span style=&quot;color:blue;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:maroon;&quot;&gt;Label&lt;/span&gt; &lt;span style=&quot;color:red;&quot;&gt;ID&lt;/span&gt;&lt;span style=&quot;color:blue;&quot;&gt;=&quot;Label3&quot;&lt;/span&gt; &lt;span style=&quot;color:red;&quot;&gt;runat&lt;/span&gt;&lt;span style=&quot;color:blue;&quot;&gt;=&quot;server&quot;&lt;/span&gt; &lt;span style=&quot;color:red;&quot;&gt;Text&lt;/span&gt;&lt;span style=&quot;color:blue;&quot;&gt;=&quot;Image&quot;&gt;&lt;!--&lt;/span--&gt;&lt;span style=&quot;color:maroon;&quot;&gt;asp&lt;/span&gt;&lt;span style=&quot;color:blue;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:maroon;&quot;&gt;Label&lt;/span&gt;&lt;span style=&quot;color:blue;&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt; &lt;span style=&quot;color:blue;&quot;&gt;&lt;&lt;/span&gt;&lt;span style=&quot;color:maroon;&quot;&gt;asp&lt;/span&gt;&lt;span style=&quot;color:blue;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:maroon;&quot;&gt;FileUpload&lt;/span&gt; &lt;span style=&quot;color:red;&quot;&gt;ID&lt;/span&gt;&lt;span style=&quot;color:blue;&quot;&gt;=&quot;FileUpload1&quot;&lt;/span&gt; &lt;span style=&quot;color:red;&quot;&gt;runat&lt;/span&gt;&lt;span style=&quot;color:blue;&quot;&gt;=&quot;server&quot;&lt;/span&gt; &lt;span style=&quot;color:blue;&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt; &lt;span style=&quot;color:blue;&quot;&gt;&lt;&lt;/span&gt;&lt;span style=&quot;color:maroon;&quot;&gt;asp&lt;/span&gt;&lt;span style=&quot;color:blue;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:maroon;&quot;&gt;Button&lt;/span&gt; &lt;span style=&quot;color:red;&quot;&gt;ID&lt;/span&gt;&lt;span style=&quot;color:blue;&quot;&gt;=&quot;Button1&quot;&lt;/span&gt; &lt;span style=&quot;color:red;&quot;&gt;runat&lt;/span&gt;&lt;span style=&quot;color:blue;&quot;&gt;=&quot;server&quot;&lt;/span&gt; &lt;span style=&quot;color:red;&quot;&gt;Text&lt;/span&gt;&lt;span style=&quot;color:blue;&quot;&gt;=&quot;Upload&quot;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;div align=&quot;center&quot;&gt;&lt;p class=&quot;ArticleManager&quot;&gt;&lt;img src=&quot;http://www.beansoftware.com/ASP.NET-Tutorials/Images/Binary-Data-Upload-Images.jpg&quot; /&gt;&lt;br /&gt;Uploading Images&lt;/p&gt;&lt;/div&gt; &lt;p class=&quot;ArticleText&quot;&gt;As shown above, we are using Fileupload control to browse picture files on hard disk.  FileUpload control is a composite control which includes a textbox and browse button together.  To add this control, simply drag and drop FileUpload control from Toolbox as shown below.&lt;/p&gt; &lt;div align=&quot;center&quot;&gt;&lt;p class=&quot;ArticleText&quot;&gt;&lt;img src=&quot;http://www.beansoftware.com/ASP.NET-Tutorials/Images/Binary-Data-Toolbox.jpg&quot; /&gt;&lt;br /&gt;File upload control on toolbox&lt;/p&gt;&lt;/div&gt; &lt;p class=&quot;ArticleText&quot;&gt;Once user selects appropriate picture file using FileUpload control,  click upload button which inserts selected image into PictureTable as new record.  The logic to insert the image into PictureTable is handled in Click event of Upload button as shown below.&lt;/p&gt; &lt;p class=&quot;ArticleText&quot;&gt;&lt;span style=&quot;color:blue;&quot;&gt; Protected&lt;/span&gt;&lt;span&gt; &lt;span style=&quot;color:blue;&quot;&gt;Sub&lt;/span&gt; Upload_Click(&lt;span style=&quot;color:blue;&quot;&gt;ByVal&lt;/span&gt;  sender &lt;span style=&quot;color:blue;&quot;&gt;As&lt;/span&gt; &lt;span style=&quot;color:blue;&quot;&gt;Object&lt;/span&gt;, &lt;span style=&quot;color:blue;&quot;&gt;ByVal&lt;/span&gt; e &lt;span style=&quot;color:blue;&quot;&gt;As&lt;/span&gt;  System.EventArgs) &lt;span style=&quot;color:blue;&quot;&gt;Handles&lt;/span&gt; Upload.Click&lt;/span&gt;&lt;br /&gt;&lt;span&gt;        &lt;span style=&quot;color:blue;&quot;&gt;Dim&lt;/span&gt; fileUpload1 &lt;span style=&quot;color:blue;&quot;&gt;As&lt;/span&gt;  FileUpload = &lt;span style=&quot;color:blue;&quot;&gt;CType&lt;/span&gt;(&lt;span style=&quot;color:blue;&quot;&gt;Me&lt;/span&gt;.FindControl(&lt;span style=&quot;color:maroon;&quot;&gt;&quot;fileUpload1&quot;&lt;/span&gt;),  FileUpload)&lt;/span&gt;&lt;br /&gt;&lt;span&gt;        &lt;span style=&quot;color:green;&quot;&gt;&#39;Make sure a file has been successfully uploaded&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;        &lt;span style=&quot;color:blue;&quot;&gt;If&lt;/span&gt; fileUpload1.PostedFile &lt;span style=&quot;color:blue;&quot;&gt;Is&lt;/span&gt; &lt;span style=&quot;color:blue;&quot;&gt;Nothing&lt;/span&gt; &lt;span style=&quot;color:blue;&quot;&gt;OrElse&lt;/span&gt; &lt;span style=&quot;color:blue;&quot;&gt;String&lt;/span&gt;.IsNullOrEmpty(fileUpload1.PostedFile.FileName) &lt;span style=&quot;color:blue;&quot;&gt;OrElse&lt;/span&gt; fileUpload1.PostedFile.InputStream &lt;span style=&quot;color:blue;&quot;&gt;Is&lt;/span&gt; &lt;span style=&quot;color:blue;&quot;&gt;Nothing&lt;/span&gt; &lt;span style=&quot;color:blue;&quot;&gt;Then&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;             Label1.Text = &lt;span style=&quot;color:maroon;&quot;&gt;&quot;Please Upload Valid  picture file&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;             &lt;span style=&quot;color:blue;&quot;&gt;Exit&lt;/span&gt; &lt;span style=&quot;color:blue;&quot;&gt;Sub&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;        &lt;span style=&quot;color:blue;&quot;&gt;End&lt;/span&gt; &lt;span style=&quot;color:blue;&quot;&gt;If&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;        &lt;span style=&quot;color:green;&quot;&gt;&#39;Make sure we are dealing with a JPG or GIF file&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;        &lt;span style=&quot;color:blue;&quot;&gt;Dim&lt;/span&gt; extension &lt;span style=&quot;color:blue;&quot;&gt;As&lt;/span&gt; &lt;span style=&quot;color:blue;&quot;&gt;String&lt;/span&gt; =  System.IO.Path.GetExtension(fileUpload1.PostedFile.FileName).ToLower()&lt;/span&gt;&lt;br /&gt;&lt;span&gt;        &lt;span style=&quot;color:blue;&quot;&gt;Dim&lt;/span&gt; MIMEType &lt;span style=&quot;color:blue;&quot;&gt;As&lt;/span&gt; &lt;span style=&quot;color:blue;&quot;&gt;String&lt;/span&gt; = &lt;span style=&quot;color:blue;&quot;&gt;Nothing&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;        &lt;span style=&quot;color:blue;&quot;&gt;Select&lt;/span&gt; &lt;span style=&quot;color:blue;&quot;&gt;Case&lt;/span&gt;  extension&lt;/span&gt;&lt;br /&gt;&lt;span&gt;             &lt;span style=&quot;color:blue;&quot;&gt;Case&lt;/span&gt; &lt;span style=&quot;color:maroon;&quot;&gt; &quot;.gif&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;                 MIMEType = &lt;span style=&quot;color:maroon;&quot;&gt;&quot;image/gif&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;             &lt;span style=&quot;color:blue;&quot;&gt;Case&lt;/span&gt; &lt;span style=&quot;color:maroon;&quot;&gt; &quot;.jpg&quot;&lt;/span&gt;, &lt;span style=&quot;color:maroon;&quot;&gt;&quot;.jpeg&quot;&lt;/span&gt;, &lt;span style=&quot;color:maroon;&quot;&gt;&quot;.jpe&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;                 MIMEType = &lt;span style=&quot;color:maroon;&quot;&gt;&quot;image/jpeg&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;             &lt;span style=&quot;color:blue;&quot;&gt;Case&lt;/span&gt; &lt;span style=&quot;color:maroon;&quot;&gt;&quot;.png&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;                 MIMEType = &lt;span style=&quot;color:maroon;&quot;&gt;&quot;image/png&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;             &lt;span style=&quot;color:blue;&quot;&gt;Case&lt;/span&gt; &lt;span style=&quot;color:blue;&quot;&gt;Else&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;                 &lt;span style=&quot;color:green;&quot;&gt;&#39;Invalid file type uploaded&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;                 Label1.Text = &lt;span style=&quot;color:maroon;&quot;&gt;&quot;Not a Valid file  format&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;                 &lt;span style=&quot;color:blue;&quot;&gt;Exit&lt;/span&gt; &lt;span style=&quot;color:blue;&quot;&gt; Sub&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;        &lt;span style=&quot;color:blue;&quot;&gt;End&lt;/span&gt; &lt;span style=&quot;color:blue;&quot;&gt;Select&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;        &lt;span style=&quot;color:green;&quot;&gt;&#39;Connect to the database and insert a new record into  Products&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;        &lt;span style=&quot;color:blue;&quot;&gt;Using&lt;/span&gt; myConnection &lt;span style=&quot;color:blue;&quot;&gt;As&lt;/span&gt; &lt;span style=&quot;color:blue;&quot;&gt;New&lt;/span&gt;  SqlConnection(ConfigurationManager.ConnectionStrings(&lt;span style=&quot;color:maroon;&quot;&gt;&quot;ImageGalleryConnectionString&quot;&lt;/span&gt;).ConnectionString)&lt;/span&gt;&lt;br /&gt;&lt;span&gt;             &lt;span style=&quot;color:blue;&quot;&gt;Const&lt;/span&gt; SQL &lt;span style=&quot;color:blue;&quot;&gt; As&lt;/span&gt; &lt;span style=&quot;color:blue;&quot;&gt;String&lt;/span&gt; = &lt;span style=&quot;color:maroon;&quot;&gt; &quot;INSERT INTO [Pictures] ([Title], [MIMEType], [Image]) VALUES (@Title, @MIMEType,  @ImageData)&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;             &lt;span style=&quot;color:blue;&quot;&gt;Dim&lt;/span&gt; myCommand &lt;span style=&quot;color:blue;&quot;&gt;As&lt;/span&gt; &lt;span style=&quot;color:blue;&quot;&gt;New&lt;/span&gt;  SqlCommand(SQL, myConnection)&lt;/span&gt;&lt;br /&gt;&lt;span&gt;             myCommand.Parameters.AddWithValue(&lt;span style=&quot;color:maroon;&quot;&gt;&quot;@Title&quot;&lt;/span&gt;,  TextBox1.Text.Trim())&lt;/span&gt;&lt;br /&gt;&lt;span&gt;             myCommand.Parameters.AddWithValue(&lt;span style=&quot;color:maroon;&quot;&gt;&quot;@MIMEType&quot;&lt;/span&gt;,  MIMEType)&lt;/span&gt;&lt;br /&gt;&lt;span&gt;             &lt;span style=&quot;color:green;&quot;&gt;&#39;Load FileUpload&#39;s InputStream into Byte  array&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;             &lt;span style=&quot;color:blue;&quot;&gt;Dim&lt;/span&gt;  imageBytes(fileUpload1.PostedFile.InputStream.Length) &lt;span style=&quot;color:blue;&quot;&gt; As&lt;/span&gt; &lt;span style=&quot;color:blue;&quot;&gt;Byte&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;             fileUpload1.PostedFile.InputStream.Read(imageBytes, 0,  imageBytes.Length)&lt;/span&gt;&lt;br /&gt;&lt;span&gt;             myCommand.Parameters.AddWithValue(&lt;span style=&quot;color:maroon;&quot;&gt;&quot;@ImageData&quot;&lt;/span&gt;,  imageBytes)&lt;/span&gt;&lt;br /&gt;&lt;span&gt;             myConnection.Open()&lt;/span&gt;&lt;br /&gt;&lt;span&gt;             myCommand.ExecuteNonQuery()&lt;/span&gt;&lt;br /&gt;&lt;span&gt;             myConnection.Close()&lt;/span&gt;&lt;br /&gt;&lt;span&gt;        &lt;span style=&quot;color:blue;&quot;&gt;End&lt;/span&gt; &lt;span style=&quot;color:blue;&quot;&gt;Using&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;    &lt;span style=&quot;color:blue;&quot;&gt;End&lt;/span&gt; &lt;span style=&quot;color:blue;&quot;&gt;Sub&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class=&quot;ArticleText&quot;&gt;Once the user has selected a file and posted back the form by clicking the &quot;Upload&quot; button,  the binary contents of the specified file are posted back to the web server.  From the server-side code, this binary data is available through the FileUpload control&#39;s PostedFile.InputStream property.&lt;/p&gt; &lt;p class=&quot;ArticleText&quot;&gt;This event handler starts off by ensuring that a file has been uploaded.  It then determines the MIME type based on the file extension of the uploaded file.  You can observe how @ImageData parameter is set.  First, a byte array named imageBytes is created and sized to the Length of the InputStream of the uploaded file.  Next, this byte array is filled with the binary contents from the InputStream using the Read method.  It&#39;s this byte array that is specified as the @ImageData&#39;s value.&lt;/p&gt; &lt;h2&gt;Displaying binary Data&lt;/h2&gt; &lt;p class=&quot;ArticleText&quot;&gt;Regardless of what technique you employ to store the data in the database,  in order to retrieve and display the binary data we need to create a new ASP.NET page for this task.  This page, named DisplayPicture.aspx, will be passed ImageID through the Querystring parameter  and return the binary data from the specified product&#39;s Image field.  Once completed, the particular picture can be viewed by browsing the link to view uploaded images. For example&lt;br /&gt;http://localhost:3219/BinaryDataVb/Displaypicture.aspx?ImageID=5. &lt;/p&gt; &lt;p class=&quot;ArticleText&quot;&gt;Therefore, to display an image on a web page, we can use an Image control whose ImageUrl property is  set to the appropriate URL.&lt;/p&gt; &lt;p class=&quot;ArticleText&quot;&gt;&lt;span style=&quot;color:blue;&quot;&gt; Protected&lt;/span&gt;&lt;span&gt; &lt;span style=&quot;color:blue;&quot;&gt;Sub&lt;/span&gt; Page_Load(&lt;span style=&quot;color:blue;&quot;&gt;ByVal&lt;/span&gt;  sender &lt;span style=&quot;color:blue;&quot;&gt;As&lt;/span&gt; &lt;span style=&quot;color:blue;&quot;&gt;Object&lt;/span&gt;, &lt;span style=&quot;color:blue;&quot;&gt;ByVal&lt;/span&gt; e &lt;span style=&quot;color:blue;&quot;&gt;As&lt;/span&gt;  System.EventArgs) &lt;span style=&quot;color:blue;&quot;&gt;Handles&lt;/span&gt; &lt;span style=&quot;color:blue;&quot;&gt;Me&lt;/span&gt;.Load&lt;/span&gt;&lt;br /&gt;&lt;span&gt;        &lt;span style=&quot;color:blue;&quot;&gt;Dim&lt;/span&gt; ImageID &lt;span style=&quot;color:blue;&quot;&gt;As&lt;/span&gt; &lt;span style=&quot;color:blue;&quot;&gt;Integer&lt;/span&gt; = Convert.ToInt32(Request.QueryString(&lt;span style=&quot;color:maroon;&quot;&gt;&quot;ImageID&quot;&lt;/span&gt;))&lt;/span&gt;&lt;br /&gt;&lt;span&gt; &lt;/span&gt;&lt;br /&gt;&lt;span&gt;        &lt;span style=&quot;color:green;&quot;&gt;&#39;Connect to the database and bring back the image  contents &amp;amp; MIME type for the specified picture&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;        &lt;span style=&quot;color:blue;&quot;&gt;Using&lt;/span&gt; myConnection &lt;span style=&quot;color:blue;&quot;&gt;As&lt;/span&gt; &lt;span style=&quot;color:blue;&quot;&gt;New&lt;/span&gt;  SqlConnection(ConfigurationManager.ConnectionStrings(&lt;span style=&quot;color:maroon;&quot;&gt;&quot;NorthwindConnection&quot;&lt;/span&gt;).ConnectionString)&lt;/span&gt;&lt;br /&gt;&lt;span&gt; &lt;/span&gt;&lt;a href=&quot;javascript:void(0)&quot; tabindex=&quot;10&quot; onclick=&quot;return false;&quot;&gt;&lt;span&gt;Publish Post&lt;/span&gt;&lt;/a&gt;&lt;br /&gt;&lt;span&gt;             &lt;span style=&quot;color:blue;&quot;&gt;Const&lt;/span&gt; SQL &lt;span style=&quot;color:blue;&quot;&gt; As&lt;/span&gt; &lt;span style=&quot;color:blue;&quot;&gt;String&lt;/span&gt; = &lt;span style=&quot;color:maroon;&quot;&gt; &quot;SELECT [MIMEType], [Image] FROM [PictureTable] WHERE [ImageID] = @ImageID&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;             &lt;span style=&quot;color:blue;&quot;&gt;Dim&lt;/span&gt; myCommand &lt;span style=&quot;color:blue;&quot;&gt;As&lt;/span&gt; &lt;span style=&quot;color:blue;&quot;&gt;New&lt;/span&gt;  SqlCommand(SQL, myConnection)&lt;/span&gt;&lt;br /&gt;&lt;span&gt;             myCommand.Parameters.AddWithValue(&lt;span style=&quot;color:maroon;&quot;&gt;&quot;@ImageID&quot;&lt;/span&gt;,  ImageID)&lt;/span&gt;&lt;br /&gt;&lt;span&gt; &lt;/span&gt;&lt;br /&gt;&lt;span&gt;             myConnection.Open()&lt;/span&gt;&lt;br /&gt;&lt;span&gt;             &lt;span style=&quot;color:blue;&quot;&gt;Dim&lt;/span&gt; myReader &lt;span style=&quot;color:blue;&quot;&gt;As&lt;/span&gt; SqlDataReader = myCommand.ExecuteReader&lt;/span&gt;&lt;br /&gt;&lt;span&gt; &lt;/span&gt;&lt;br /&gt;&lt;span&gt;             &lt;span style=&quot;color:blue;&quot;&gt;If&lt;/span&gt; myReader.Read &lt;span style=&quot;color:blue;&quot;&gt;Then&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;                 Response.ContentType = myReader(&lt;span style=&quot;color:maroon;&quot;&gt;&quot;MIMEType&quot;&lt;/span&gt;).ToString()&lt;/span&gt;&lt;br /&gt;&lt;span&gt;                 Response.BinaryWrite(myReader(&lt;span style=&quot;color:maroon;&quot;&gt;&quot;Image&quot;&lt;/span&gt;))&lt;/span&gt;&lt;br /&gt;&lt;span&gt;             &lt;span style=&quot;color:blue;&quot;&gt;End&lt;/span&gt; &lt;span style=&quot;color:blue;&quot;&gt;If&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color:blue;&quot;&gt;  &lt;/span&gt;&lt;br /&gt;&lt;span&gt;             myReader.Close()&lt;/span&gt;&lt;br /&gt;&lt;span&gt;             myConnection.Close()&lt;/span&gt;&lt;br /&gt;&lt;span&gt;        &lt;span style=&quot;color:blue;&quot;&gt;End&lt;/span&gt; &lt;span style=&quot;color:blue;&quot;&gt;Using&lt;/span&gt;&lt;/span&gt; &lt;/p&gt;&lt;p&gt;&lt;span&gt;    &lt;span style=&quot;color:blue;&quot;&gt;End&lt;/span&gt; &lt;span style=&quot;color:blue;&quot;&gt;Sub&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;i&gt;Code listing for DisplayPicture.aspx&lt;/i&gt;&lt;/p&gt; &lt;div align=&quot;center&quot;&gt;&lt;p class=&quot;ArticleText&quot;&gt;&lt;img src=&quot;http://www.beansoftware.com/ASP.NET-Tutorials/Images/Binary-Data-QueryString.jpg&quot; /&gt;&lt;br /&gt;Displaying picture using QueryString parameter&lt;/p&gt;&lt;/div&gt; &lt;p class=&quot;ArticleText&quot;&gt;The DisplayPicture.aspx does not include any HTML markup in the .aspx page. In the code-behind class&#39;s Page_Load event handler, the specified Pictures row&#39;s MIMEType and Image are retrieved from the database using ADO.NET code. Next, the page&#39;s ContentType is set to the value of the MIMEType field and the binary data is emitted using Response.BinaryWrite(Image): When DisplayPicture.aspx page complete, the image can be viewed by either directly visiting the URL.&lt;/p&gt; &lt;p class=&quot;ArticleText&quot;&gt;On the same way, we could call .zip, .pdf or any other binary file, stored in database system. If you want to get .zip file from database, you don&#39;t need to use Image control. Instead of using src parameter of Image control, for .zip and .pdf files use href parameter of hyperlink tag (e.g. &lt;a href=&quot;http://www.blogger.com/GetZipFromDB.aspx?id=5&quot;&gt;Get great zip file&lt;/a&gt; ) &lt;/p&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;octopus east java baker&lt;/div&gt;</description><link>http://scriptster.blogspot.com/2007/10/storing-binary-data-to-database-using.html</link><author>noreply@blogger.com (Octopus)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-2977499297091575918.post-4132107971390344998</guid><pubDate>Fri, 21 Sep 2007 07:00:00 +0000</pubDate><atom:updated>2007-09-21T00:01:37.090-07:00</atom:updated><title>SQL Server Transact-SQL General Tips Part III</title><description>&lt;p&gt;         By :  &lt;a id=&quot;ctl00_ctl00_ContentPlaceHolder1_articleContent_authDateCntrl_authLbl&quot; href=&quot;http://www.sql-server-performance.com/authors/bradm.aspx&quot;&gt;Brad McGehee&lt;/a&gt;&lt;br /&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: rgb(51, 51, 51); font-family: &#39;Verdana&#39;,&#39;sans-serif&#39;;&quot;&gt;&lt;br /&gt;When using the WHILE statement, don&#39;t avoid the use of BREAK just because some people consider it bad programming form&lt;/span&gt;&lt;/strong&gt;&lt;span style=&quot;color: rgb(51, 51, 51); font-family: &#39;Verdana&#39;,&#39;sans-serif&#39;;&quot;&gt;. Often when creating Transact-SQL code using the WHILE statement, you can avoid using BREAK by moving a few lines of code around. If this works in your case, then by all means don&#39;t use BREAK. But if your efforts to avoid using BREAK require you to add additional lines of code that makes your code run slower, then don&#39;t do that. Sometimes, using BREAK can speed up the execution of your WHILE statements. [6.5, 7.0, 2000, 2005] &lt;em&gt;&lt;span style=&quot;font-family: &#39;Verdana&#39;,&#39;sans-serif&#39;;&quot;&gt;Updated 6-12-2006&lt;/span&gt;&lt;/em&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class=&quot;asterisk&quot; style=&quot;margin: auto 0in;&quot;&gt;&lt;span style=&quot;font-family: &#39;Verdana&#39;,&#39;sans-serif&#39;;&quot;&gt;&lt;span style=&quot;color:#000080;&quot;&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;*****&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: rgb(51, 51, 51); font-family: &#39;Verdana&#39;,&#39;sans-serif&#39;;&quot;&gt;One of the advantages of using SQL Server for n-tier applications is that you can offload much (if not most) of the data processing work from the other tiers&lt;/span&gt;&lt;/strong&gt;&lt;span style=&quot;color: rgb(51, 51, 51); font-family: &#39;Verdana&#39;,&#39;sans-serif&#39;;&quot;&gt; and place it on SQL Server. The more work you can perform within SQL Server, the fewer the network roundtrips that need to be made between the various tiers and SQL Server. And generally the fewer the network roundtrips, the more scalable and faster the application becomes.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p&gt;&lt;span style=&quot;color: rgb(51, 51, 51); font-family: &#39;Verdana&#39;,&#39;sans-serif&#39;;&quot;&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;But in some applications, such as those than involve complex math, SQL Server has traditionally been weak. In these cases, complex math often could not be performed within SQL Server, instead it had to be performed on another tier, causing more network roundtrips than desired.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p&gt;&lt;span style=&quot;color: rgb(51, 51, 51); font-family: &#39;Verdana&#39;,&#39;sans-serif&#39;;&quot;&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;By using user-defined functions (UDFs), this is becoming less of a problem. UDFs allow developers to perform many complex math functions from within SQL Server, functions that previously could only be performed outside of SQL Server. By taking advantage of UDFs, more work can stay with SQL Server instead of being shuttled to another tier, reducing network roundtrips, and potentially boosting your application&#39;s performance.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p&gt;&lt;span style=&quot;color: rgb(51, 51, 51); font-family: &#39;Verdana&#39;,&#39;sans-serif&#39;;&quot;&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;Obviously, boosting your application&#39;s performance is not as simple as moving math functions to SQL Server, but it is one feature of SQL Server 2000/2005 that developers can take advantage of in order to boost their application&#39;s scalability and performance. [2000, 2005] &lt;em&gt;&lt;span style=&quot;font-family: &#39;Verdana&#39;,&#39;sans-serif&#39;;&quot;&gt;Updated 6-12-2006&lt;/span&gt;&lt;/em&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class=&quot;asterisk&quot; style=&quot;margin: auto 0in;&quot;&gt;&lt;span style=&quot;font-family: &#39;Verdana&#39;,&#39;sans-serif&#39;;&quot;&gt;&lt;span style=&quot;color:#000080;&quot;&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;*****&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p&gt;&lt;span style=&quot;color: rgb(51, 51, 51); font-family: &#39;Verdana&#39;,&#39;sans-serif&#39;;&quot;&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;SQL Server 2000/2005 offers a data type called &quot;table.&quot; Its main purpose is for the temporary storage of a set of rows. A variable, of type &quot;table,&quot; behaves as if it is a local variable. And like local variables, it has a limited scope, which is within the batch, function, or stored procedure in which it was declared. In most cases, a table variable can be used like a normal table. SELECTs, INSERTs, UPDATEs, and DELETEs can all be made against a table variable.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: rgb(51, 51, 51); font-family: &#39;Verdana&#39;,&#39;sans-serif&#39;;&quot;&gt;For better performance, if you need a temporary table in your Transact-SQL code, consider using a table variable instead of creating a conventional temporary table.&lt;/span&gt;&lt;/strong&gt;&lt;span style=&quot;color: rgb(51, 51, 51); font-family: &#39;Verdana&#39;,&#39;sans-serif&#39;;&quot;&gt; Table variables are often faster, but not always. In addition, table variables found in stored procedures result in fewer compilations (than when using temporary tables), and transactions using table variables only last as long as the duration of an update on the table variable, requiring less locking and logging resources. [2000, 2005] &lt;em&gt;&lt;span style=&quot;font-family: &#39;Verdana&#39;,&#39;sans-serif&#39;;&quot;&gt;Updated 10-02-2006&lt;/span&gt;&lt;/em&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class=&quot;asterisk&quot; style=&quot;margin: auto 0in;&quot;&gt;&lt;span style=&quot;font-family: &#39;Verdana&#39;,&#39;sans-serif&#39;;&quot;&gt;&lt;span style=&quot;color:#000080;&quot;&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;*****&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: rgb(51, 51, 51); font-family: &#39;Verdana&#39;,&#39;sans-serif&#39;;&quot;&gt;Don&#39;t repeatedly reuse the same function to calculate the same result over and over within your Transact-SQL code&lt;/span&gt;&lt;/strong&gt;&lt;span style=&quot;color: rgb(51, 51, 51); font-family: &#39;Verdana&#39;,&#39;sans-serif&#39;;&quot;&gt;. For example, if you need to reuse the value of the length of a string over and over within your code, perform the LEN function once on the string, and this assign the result to a variable, and then use this variable, over and over, as needed in your code. Don&#39;t recalculate the same value over and over again by reusing the LEN function each time you need the value, as it wastes SQL Server resources and hurts performance. [6.5, 7.0, 2000, 2005] &lt;em&gt;&lt;span style=&quot;font-family: &#39;Verdana&#39;,&#39;sans-serif&#39;;&quot;&gt;Updated 10-02-2006&lt;/span&gt;&lt;/em&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class=&quot;asterisk&quot; style=&quot;margin: auto 0in;&quot;&gt;&lt;span style=&quot;font-family: &#39;Verdana&#39;,&#39;sans-serif&#39;;&quot;&gt;&lt;span style=&quot;color:#000080;&quot;&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;*****&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p&gt;&lt;span style=&quot;color: rgb(51, 51, 51); font-family: &#39;Verdana&#39;,&#39;sans-serif&#39;;&quot;&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;Many developers choose to use an &lt;strong&gt;&lt;span style=&quot;font-family: &#39;Verdana&#39;,&#39;sans-serif&#39;;&quot;&gt;identify column&lt;/span&gt;&lt;/strong&gt; at their primary key. By design, an identity column does not guarantee that that each newly created row will be consecutively numbered. This means there will most likely be occasional gaps in the identity column numbering scheme. For most applications, occasional gaps in the identity column present no problems.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p&gt;&lt;span style=&quot;color: rgb(51, 51, 51); font-family: &#39;Verdana&#39;,&#39;sans-serif&#39;;&quot;&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;On the other hand, some developers don&#39;t like these occasional gaps, trying to avoid them. With some clever use of INSTEAD OF triggers in SQL Server 2000,2005, it is possible prevent these numbering gaps. But at what cost?&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p&gt;&lt;span style=&quot;color: rgb(51, 51, 51); font-family: &#39;Verdana&#39;,&#39;sans-serif&#39;;&quot;&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;The problem with trying to force an identify column to number consecutively without gaps can lead to locking and scalability problems, hurting performance. So the recommendation is not to try to get around the identify column&#39;s built-in method of working. If you do, expect performance problems. [2000, 2005] &lt;em&gt;&lt;span style=&quot;font-family: &#39;Verdana&#39;,&#39;sans-serif&#39;;&quot;&gt;Updated 10-02-2006&lt;/span&gt;&lt;/em&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class=&quot;asterisk&quot; style=&quot;margin: auto 0in;&quot;&gt;&lt;span style=&quot;font-family: &#39;Verdana&#39;,&#39;sans-serif&#39;;&quot;&gt;&lt;span style=&quot;color:#000080;&quot;&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;*****&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p&gt;&lt;span style=&quot;color: rgb(51, 51, 51); font-family: &#39;Verdana&#39;,&#39;sans-serif&#39;;&quot;&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;If you use the &lt;strong&gt;&lt;span style=&quot;font-family: &#39;Verdana&#39;,&#39;sans-serif&#39;;&quot;&gt;BULK INSERT&lt;/span&gt;&lt;/strong&gt; to import data into SQL Server, seriously consider using the TABLOCK hint along with it. This will prevent SQL Server from running out of locks during vary large imports, and also boost performance due to the reduction of lock contention. [7.0, 2000, 2005] &lt;em&gt;&lt;span style=&quot;font-family: &#39;Verdana&#39;,&#39;sans-serif&#39;;&quot;&gt;Added 11-22-2004&lt;/span&gt;&lt;/em&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class=&quot;asterisk&quot; style=&quot;margin: auto 0in;&quot;&gt;&lt;span style=&quot;font-family: &#39;Verdana&#39;,&#39;sans-serif&#39;;&quot;&gt;&lt;span style=&quot;color:#000080;&quot;&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;*****&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;span style=&quot;color: rgb(51, 51, 51); font-family: &#39;Verdana&#39;,&#39;sans-serif&#39;;&quot;&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;To help identify long running queries, &lt;strong&gt;&lt;span style=&quot;font-family: &#39;Verdana&#39;,&#39;sans-serif&#39;;&quot;&gt;use the SQL Server Profiler Create Trace Wizard&lt;/span&gt;&lt;/strong&gt; to run the &quot;TSQL By Duration&quot; trace. You can specify the length of the long running queries you are trying to identify (such as over 1000 milliseconds), and then have these recorded in a log for you to investigate later. [7.0]&lt;/span&gt;&lt;/span&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;octopus east java baker&lt;/div&gt;</description><link>http://scriptster.blogspot.com/2007/09/sql-server-transact-sql-general-tips_21.html</link><author>noreply@blogger.com (Octopus)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-2977499297091575918.post-512356337615514280</guid><pubDate>Fri, 21 Sep 2007 06:59:00 +0000</pubDate><atom:updated>2007-09-21T00:00:45.578-07:00</atom:updated><title>SQL Server Transact-SQL General Tips Part II</title><description>&lt;p&gt;         By :  &lt;a id=&quot;ctl00_ctl00_ContentPlaceHolder1_articleContent_authDateCntrl_authLbl&quot; href=&quot;http://www.sql-server-performance.com/authors/bradm.aspx&quot;&gt;Brad McGehee&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: rgb(51, 51, 51); font-family: &#39;Verdana&#39;,&#39;sans-serif&#39;;&quot;&gt;Instead of using temporary tables, consider using a derived table instead&lt;/span&gt;&lt;/strong&gt;&lt;span style=&quot;color: rgb(51, 51, 51); font-family: &#39;Verdana&#39;,&#39;sans-serif&#39;;&quot;&gt;. A derived table is the result of using a SELECT statement in the FROM clause of an existing SELECT statement. By using derived tables instead of temporary tables, you can reduce I/O and often boost your application&#39;s performance. [7.0, 2000, 2005] &lt;em&gt;&lt;span style=&quot;font-family: &#39;Verdana&#39;,&#39;sans-serif&#39;;&quot;&gt;Updated 6-12-2006&lt;/span&gt;&lt;/em&gt; &lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class=&quot;asterisk&quot; style=&quot;margin: auto 0in;&quot;&gt;&lt;span style=&quot;font-family: &#39;Verdana&#39;,&#39;sans-serif&#39;;&quot;&gt;&lt;span style=&quot;color:#000080;&quot;&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;*****&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: rgb(51, 51, 51); font-family: &#39;Verdana&#39;,&#39;sans-serif&#39;;&quot;&gt;Sometimes, it is handy to be able to perform some calculation on one or more columns of a record, and then take the result of that calculation and then add it to similar calculations performed on other related records to find a grand total.&lt;/span&gt;&lt;/strong&gt;&lt;span style=&quot;color: rgb(51, 51, 51); font-family: &#39;Verdana&#39;,&#39;sans-serif&#39;;&quot;&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p&gt;&lt;span style=&quot;color: rgb(51, 51, 51); font-family: &#39;Verdana&#39;,&#39;sans-serif&#39;;&quot;&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;For example, let&#39;s say you want to find the total dollar cost of an invoice. An invoice will generally involve a header record and one or more detail records. Each detail record will represent a line item on the invoice. In order to calculate the total dollar cost of an invoice, based on two or more line items, you would need to multiply the quantity of each item sold times the price of each item. Then, you would need to add the total price of each line item together in order to get the total dollar cost of the entire invoice. To keep this example simple, let&#39;s ignore things like discounts, taxes, shipping, etc.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p&gt;&lt;span style=&quot;color: rgb(51, 51, 51); font-family: &#39;Verdana&#39;,&#39;sans-serif&#39;;&quot;&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;One way to accomplish this task would be to use a cursor; like we see below (we are using the Northwind database for this example code):&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class=&quot;textcode&quot; style=&quot;margin: auto 0in;&quot;&gt;&lt;span style=&quot;font-family:Courier New;font-size:85%;color:#0033ff;&quot;&gt;DECLARE @LineTotal money --Declare variables&lt;br /&gt;DECLARE @InvoiceTotal money&lt;br /&gt;SET @LineTotal = 0 --Set variables to 0&lt;br /&gt;SET @InvoiceTotal = 0&lt;br /&gt;&lt;br /&gt;DECLARE Line_Item_Cursor CURSOR FOR --Declare the cursor&lt;br /&gt;&lt;br /&gt;SELECT UnitPrice*Quantity --Multiply unit price times quantity ordered&lt;br /&gt;FROM [order details]&lt;br /&gt;WHERE orderid = 10248 --We are only concerned with invoice 10248&lt;br /&gt;&lt;br /&gt;OPEN Line_Item_Cursor --Open the cursor&lt;br /&gt;FETCH NEXT FROM Line_Item_Cursor INTO @LineTotal --Fetch next record&lt;br /&gt;WHILE @@FETCH_STATUS = 0&lt;br /&gt;&lt;br /&gt;BEGIN&lt;br /&gt;SET @InvoiceTotal = @InvoiceTotal + @LineTotal --Summarize line items&lt;br /&gt;FETCH NEXT FROM Line_Item_Cursor INTO @LineTotal&lt;br /&gt;END&lt;br /&gt;&lt;br /&gt;CLOSE Line_Item_Cursor --Close cursor&lt;br /&gt;DEALLOCATE Line_Item_Cursor --Deallocate cursor&lt;br /&gt;SELECT @InvoiceTotal InvoiceTotal --Display total value of invoice&lt;/span&gt;&lt;/p&gt; &lt;p&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;&lt;em&gt;&lt;span style=&quot;color: rgb(51, 51, 51); font-family: &#39;Verdana&#39;,&#39;sans-serif&#39;;&quot;&gt;The result for invoice number 10248 is $440.00.&lt;/span&gt;&lt;/em&gt;&lt;span style=&quot;color: rgb(51, 51, 51); font-family: &#39;Verdana&#39;,&#39;sans-serif&#39;;&quot;&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p&gt;&lt;span style=&quot;color: rgb(51, 51, 51); font-family: &#39;Verdana&#39;,&#39;sans-serif&#39;;&quot;&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;What the cursor does is to select all of the line items for invoice number 10248, then multiply the quantity ordered times the price to get a line item total, and then it takes each of the line item totals for each record and then adds them all up in order to calculate the total dollar amount for the invoice.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p&gt;&lt;span style=&quot;color: rgb(51, 51, 51); font-family: &#39;Verdana&#39;,&#39;sans-serif&#39;;&quot;&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;This all works well, but the code is long and hard to read, and performance is not great because a cursor is used. Ideally, for best performance, we need to find another way to accomplish the same goal as above, but without using a cursor.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p&gt;&lt;span style=&quot;color: rgb(51, 51, 51); font-family: &#39;Verdana&#39;,&#39;sans-serif&#39;;&quot;&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;Instead of using a cursor, let&#39;s rewrite the above code using set-based Transact-SQL instead of a cursor. Here&#39;s what the code looks like:&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class=&quot;textcode&quot; style=&quot;margin: auto 0in;&quot;&gt;&lt;span style=&quot;font-family:Courier New;font-size:85%;color:#0033ff;&quot;&gt;DECLARE @InvoiceTotal money&lt;br /&gt;SELECT @InvoiceTotal = sum(UnitPrice*Quantity)&lt;br /&gt;FROM [order details]&lt;br /&gt;WHERE orderid = 10248&lt;br /&gt;SELECT @InvoiceTotal InvoiceTotal&lt;/span&gt;&lt;/p&gt; &lt;p&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;&lt;em&gt;&lt;span style=&quot;color: rgb(51, 51, 51); font-family: &#39;Verdana&#39;,&#39;sans-serif&#39;;&quot;&gt;The result for invoice number 10248 is $440.00.&lt;/span&gt;&lt;/em&gt;&lt;span style=&quot;color: rgb(51, 51, 51); font-family: &#39;Verdana&#39;,&#39;sans-serif&#39;;&quot;&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p&gt;&lt;span style=&quot;color: rgb(51, 51, 51); font-family: &#39;Verdana&#39;,&#39;sans-serif&#39;;&quot;&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;Right away, it is obvious that this is a lot less code and that is it more readable. What may not be obvious is that it uses less server resources and performs faster. In our example--with few rows--the time difference is very small, but if many rows are involved, the time difference between the techniques can be substantial.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p&gt;&lt;span style=&quot;color: rgb(51, 51, 51); font-family: &#39;Verdana&#39;,&#39;sans-serif&#39;;&quot;&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;The secret here is to use the Transact-SQL &quot;sum&quot; function to summarize the line item totals for you, instead of relying on a cursor. You can use this same technique to help reduce your dependency on using resource-hogging cursors in much of your Transact-SQL code. [6.5, 7.0, 2000, 2005] &lt;em&gt;&lt;span style=&quot;font-family: &#39;Verdana&#39;,&#39;sans-serif&#39;;&quot;&gt;Updated 6-12-2006&lt;/span&gt;&lt;/em&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class=&quot;asterisk&quot; style=&quot;margin: auto 0in;&quot;&gt;&lt;span style=&quot;font-family: &#39;Verdana&#39;,&#39;sans-serif&#39;;&quot;&gt;&lt;span style=&quot;color:#000080;&quot;&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;*****&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: rgb(51, 51, 51); font-family: &#39;Verdana&#39;,&#39;sans-serif&#39;;&quot;&gt;While views are often convenient to use, especially for restricting users from seeing data they should not see, they aren&#39;t always good for performance&lt;/span&gt;&lt;/strong&gt;&lt;span style=&quot;color: rgb(51, 51, 51); font-family: &#39;Verdana&#39;,&#39;sans-serif&#39;;&quot;&gt;. So if database performance is your goal, avoid using views (SQL Server 2000/2005 Indexed Views are another story).&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p&gt;&lt;span style=&quot;color: rgb(51, 51, 51); font-family: &#39;Verdana&#39;,&#39;sans-serif&#39;;&quot;&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;When the Query Optimizer gets a request to run a view, it runs it just as if you had run the view&#39;s SELECT statement from the Query Analyzer or Management Studio. If fact, a view runs slightly slower than the same SELECT statement run from the Query Analyzer or Management Studio--but you probably would not notice the small difference--as it is small in simple examples like this.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p&gt;&lt;span style=&quot;color: rgb(51, 51, 51); font-family: &#39;Verdana&#39;,&#39;sans-serif&#39;;&quot;&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;Another issue with views is that they are often combined (nested) with other code, such as being embedded within another view, a stored procedure, or other T-SQL script. Doing so often makes it more difficult to identify potential performance issues.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p&gt;&lt;span style=&quot;color: rgb(51, 51, 51); font-family: &#39;Verdana&#39;,&#39;sans-serif&#39;;&quot;&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;Views don&#39;t allow you to add more restrictive WHERE clauses as needed. In other words, they can&#39;t accept input parameters, which are often needed to restrict the amount of records returned. I have seen lazy developers write generic views that return hundreds of thousands of unnecessary rows, and then user other code, such as client code, to filter only those few records that are needed. This is a great waste of SQL Server&#39;s resources.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;span style=&quot;color: rgb(51, 51, 51); font-family: &#39;Verdana&#39;,&#39;sans-serif&#39;;&quot;&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;Instead of embedding SELECT statements in a view, put them in a stored procedure for optimum performance. Not only do you get an added performance boost (in many cases), you can also use the stored procedure to restrict user access to table columns, just as you can with views. [6.5, 7.0, 2000, 2005] &lt;em&gt;&lt;span style=&quot;font-family: &#39;Verdana&#39;,&#39;sans-serif&#39;;&quot;&gt;Updated 6-12-2006&lt;/span&gt;&lt;/em&gt;&lt;/span&gt;&lt;/span&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;octopus east java baker&lt;/div&gt;</description><link>http://scriptster.blogspot.com/2007/09/sql-server-transact-sql-general-tips_20.html</link><author>noreply@blogger.com (Octopus)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-2977499297091575918.post-8034785452229151173</guid><pubDate>Fri, 21 Sep 2007 06:57:00 +0000</pubDate><atom:updated>2007-09-20T23:59:08.095-07:00</atom:updated><title>SQL Server Transact-SQL General Tips Part I</title><description>&lt;p&gt;         By :  &lt;a id=&quot;ctl00_ctl00_ContentPlaceHolder1_articleContent_authDateCntrl_authLbl&quot; href=&quot;http://www.sql-server-performance.com/authors/bradm.aspx&quot;&gt;Brad McGehee&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: rgb(51, 51, 51); font-family: &#39;Verdana&#39;,&#39;sans-serif&#39;;&quot;&gt;Don&#39;t include code, variable, or parameters that don&#39;t do anything&lt;/span&gt;&lt;/strong&gt;&lt;span style=&quot;color: rgb(51, 51, 51); font-family: &#39;Verdana&#39;,&#39;sans-serif&#39;;&quot;&gt;. This may sound obvious, but I have seen this in some off-the-shelf SQL Server-based applications. For example, you may see code like this:&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class=&quot;textcode&quot; style=&quot;margin: auto 0in;&quot;&gt;&lt;span style=&quot;font-family:Courier New;font-size:85%;color:#0033ff;&quot;&gt;SELECT column_name FROM table_name&lt;br /&gt;WHERE 1 = 0&lt;/span&gt;&lt;/p&gt; &lt;p&gt;&lt;span style=&quot;color: rgb(51, 51, 51); font-family: &#39;Verdana&#39;,&#39;sans-serif&#39;;&quot;&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;When this query is run, no rows will be returned. Obviously, this is a simple example (and most of the cases where I have seen this done have been very long queries). A query like this (even if part of a larger query) doesn&#39;t perform anything useful, and doesn&#39;t need to be run. It is just wasting SQL Server resources. In addition, I have seen more than one case where such dead code actually causes SQL Server to throw errors, preventing the code from even running. [6.5, 7.0, 2000, 2000, 2005] &lt;em&gt;&lt;span style=&quot;font-family: &#39;Verdana&#39;,&#39;sans-serif&#39;;&quot;&gt;Updated 1-24-2006&lt;/span&gt;&lt;/em&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class=&quot;asterisk&quot; style=&quot;margin: auto 0in;&quot;&gt;&lt;span style=&quot;font-family: &#39;Verdana&#39;,&#39;sans-serif&#39;;&quot;&gt;&lt;span style=&quot;color:#000080;&quot;&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;*****&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p&gt;&lt;span style=&quot;color: rgb(51, 51, 51); font-family: &#39;Verdana&#39;,&#39;sans-serif&#39;;&quot;&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;Don&#39;t be afraid to make liberal use of &lt;strong&gt;&lt;span style=&quot;font-family: &#39;Verdana&#39;,&#39;sans-serif&#39;;&quot;&gt;in-line and block comments&lt;/span&gt;&lt;/strong&gt; in your Transact-SQL code, they will not affect the performance of your application, and they will enhance your productivity when you have to come back to the code and try to modify it. [6.5, 7.0, 2000, 2005] &lt;em&gt;&lt;span style=&quot;font-family: &#39;Verdana&#39;,&#39;sans-serif&#39;;&quot;&gt;Updated 1-24-2006&lt;/span&gt;&lt;/em&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class=&quot;asterisk&quot; style=&quot;margin: auto 0in;&quot;&gt;&lt;span style=&quot;font-family: &#39;Verdana&#39;,&#39;sans-serif&#39;;&quot;&gt;&lt;span style=&quot;color:#000080;&quot;&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;*****&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p&gt;&lt;span style=&quot;color: rgb(51, 51, 51); font-family: &#39;Verdana&#39;,&#39;sans-serif&#39;;&quot;&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;If possible, &lt;strong&gt;&lt;span style=&quot;font-family: &#39;Verdana&#39;,&#39;sans-serif&#39;;&quot;&gt;avoid using SQL Server cursors&lt;/span&gt;&lt;/strong&gt;. They generally use a lot of SQL Server resources and reduce the performance and scalability of your applications. If you need to perform row-by-row operations, try to find another method to perform the task. Some options are to perform the task at the client, use tempdb tables, use derived tables, use a correlated subquery, or use the CASE statement. More often than not, there are non-cursor techniques that can be used to perform the same tasks as a SQL Server cursor. [6.5, 7.0, 2000, 2005] &lt;em&gt;&lt;span style=&quot;font-family: &#39;Verdana&#39;,&#39;sans-serif&#39;;&quot;&gt;Updated 1-24-2006&lt;/span&gt;&lt;/em&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class=&quot;asterisk&quot; style=&quot;margin: auto 0in;&quot;&gt;&lt;span style=&quot;font-family: &#39;Verdana&#39;,&#39;sans-serif&#39;;&quot;&gt;&lt;span style=&quot;color:#000080;&quot;&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;*****&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: rgb(51, 51, 51); font-family: &#39;Verdana&#39;,&#39;sans-serif&#39;;&quot;&gt;If your users perform many ad hoc queries&lt;/span&gt;&lt;/strong&gt;&lt;span style=&quot;color: rgb(51, 51, 51); font-family: &#39;Verdana&#39;,&#39;sans-serif&#39;;&quot;&gt; on your SQL Server data, and you find that many of these &quot;poorly-written&quot; queries take up an excessive amount of SQL Server resources, consider using the &quot;query governor cost limit&quot; configuration option to limit how long a query can run.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p&gt;&lt;span style=&quot;color: rgb(51, 51, 51); font-family: &#39;Verdana&#39;,&#39;sans-serif&#39;;&quot;&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;This option allows you to specify the maximum amount of &quot;seconds&quot; a query will run, and whenever the query optimizer determines that a particular query will exceed the maximum limit, the query will be aborted before it even begins.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p&gt;&lt;span style=&quot;color: rgb(51, 51, 51); font-family: &#39;Verdana&#39;,&#39;sans-serif&#39;;&quot;&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;Although the value you set for this setting is stated as &quot;seconds,&quot; it does not mean seconds like we think of seconds. Instead, it relates to the actual estimated cost of the query as calculated by the query optimizer. You may have to experiment with this value until you find one that meets your needs.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p&gt;&lt;span style=&quot;color: rgb(51, 51, 51); font-family: &#39;Verdana&#39;,&#39;sans-serif&#39;;&quot;&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;There are two ways to set this option. First, you can change it at the server level (all queries running on the server are affected by it) using sp_configure &quot;query governor cost limit,&quot; or you can set it at the connection level (only this connection is affected) by using the SET QUERY_GOVERNOR_COST_LIMIT command. [7.0, 2000, 2005] &lt;em&gt;&lt;span style=&quot;font-family: &#39;Verdana&#39;,&#39;sans-serif&#39;;&quot;&gt;Updated 1-24-2006&lt;/span&gt;&lt;/em&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class=&quot;asterisk&quot; style=&quot;margin: auto 0in;&quot;&gt;&lt;span style=&quot;font-family: &#39;Verdana&#39;,&#39;sans-serif&#39;;&quot;&gt;&lt;span style=&quot;color:#000080;&quot;&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;*****&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p&gt;&lt;span style=&quot;color: rgb(51, 51, 51); font-family: &#39;Verdana&#39;,&#39;sans-serif&#39;;&quot;&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;You may have heard of a SET command called SET ROWCOUNT. Like the TOP operator, it is designed to limit how many rows are returned from a SELECT statement. In effect, the SET ROWCOUNT and the TOP operator perform the same function.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p&gt;&lt;span style=&quot;color: rgb(51, 51, 51); font-family: &#39;Verdana&#39;,&#39;sans-serif&#39;;&quot;&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;While in most cases, using either option works equally efficiently, there are some instances (such as rows returned from an unsorted heap) where the TOP operator is more efficient than using SET ROWCOUNT. Because of this, using the TOP operator is preferable to using SET ROWCOUNT to limit the number of rows returned by a query. [6.5, 7.0, 2000, 2005] &lt;em&gt;&lt;span style=&quot;font-family: &#39;Verdana&#39;,&#39;sans-serif&#39;;&quot;&gt;Updated 1-24-2006&lt;/span&gt;&lt;/em&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class=&quot;asterisk&quot; style=&quot;margin: auto 0in;&quot;&gt;&lt;span style=&quot;font-family: &#39;Verdana&#39;,&#39;sans-serif&#39;;&quot;&gt;&lt;span style=&quot;color:#000080;&quot;&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;*****&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: rgb(51, 51, 51); font-family: &#39;Verdana&#39;,&#39;sans-serif&#39;;&quot;&gt;If you have the choice of using a join or a subquery&lt;/span&gt;&lt;/strong&gt;&lt;span style=&quot;color: rgb(51, 51, 51); font-family: &#39;Verdana&#39;,&#39;sans-serif&#39;;&quot;&gt; to perform the same task within a query, generally the join is faster. But this is not always the case, and you may want to test the query using both methods to determine which is faster for your particular application. [6.5, 7.0, 2000, 2005] &lt;em&gt;&lt;span style=&quot;font-family: &#39;Verdana&#39;,&#39;sans-serif&#39;;&quot;&gt;Updated 1-24-2006&lt;/span&gt;&lt;/em&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class=&quot;asterisk&quot; style=&quot;margin: auto 0in;&quot;&gt;&lt;span style=&quot;font-family: &#39;Verdana&#39;,&#39;sans-serif&#39;;&quot;&gt;&lt;span style=&quot;color:#000080;&quot;&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;*****&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: rgb(51, 51, 51); font-family: &#39;Verdana&#39;,&#39;sans-serif&#39;;&quot;&gt;If you need to create a primary key&lt;/span&gt;&lt;/strong&gt;&lt;span style=&quot;color: rgb(51, 51, 51); font-family: &#39;Verdana&#39;,&#39;sans-serif&#39;;&quot;&gt; (using a value meaningless to the record, other than providing a unique value for a record), many developers will use either an identity column (with an integer data type) or an uniqueindentifier data type.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p&gt;&lt;span style=&quot;color: rgb(51, 51, 51); font-family: &#39;Verdana&#39;,&#39;sans-serif&#39;;&quot;&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;If your application can use either option, then you will most likely want to choose the identity column over the uniqueindentifier column.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p&gt;&lt;span style=&quot;color: rgb(51, 51, 51); font-family: &#39;Verdana&#39;,&#39;sans-serif&#39;;&quot;&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;The reason for this is that the identity column (using the integer data type) only takes up 4 bytes, while the uniqueindentifier column takes 16 bytes. Using an identifier column will create a smaller and faster index. [7.0, 2000, 2005] &lt;em&gt;&lt;span style=&quot;font-family: &#39;Verdana&#39;,&#39;sans-serif&#39;;&quot;&gt;Updated 1-24-2006&lt;/span&gt;&lt;/em&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class=&quot;asterisk&quot; style=&quot;margin: auto 0in;&quot;&gt;&lt;span style=&quot;font-family: &#39;Verdana&#39;,&#39;sans-serif&#39;;&quot;&gt;&lt;span style=&quot;color:#000080;&quot;&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;*****&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: rgb(51, 51, 51); font-family: &#39;Verdana&#39;,&#39;sans-serif&#39;;&quot;&gt;If your application requires you to create temporary tables&lt;/span&gt;&lt;/strong&gt;&lt;span style=&quot;color: rgb(51, 51, 51); font-family: &#39;Verdana&#39;,&#39;sans-serif&#39;;&quot;&gt; for use on a global or per connection use, consider the possibility of creating indexes for these temporary tables. While most temporary tables probably won&#39;t need, or even use an index, some larger temporary tables can benefit from them. A properly designed index on a temporary table can be as great a benefit as a properly designed index on a standard database table.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p&gt;&lt;span style=&quot;color: rgb(51, 51, 51); font-family: &#39;Verdana&#39;,&#39;sans-serif&#39;;&quot;&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;In order to determine if indexes will help the performance of your applications using temporary tables, you will probably have to perform some testing. [6.5, 7.0, 2000, 2005] &lt;em&gt;&lt;span style=&quot;font-family: &#39;Verdana&#39;,&#39;sans-serif&#39;;&quot;&gt;Updated 1-24-2006&lt;/span&gt;&lt;/em&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class=&quot;asterisk&quot; style=&quot;margin: auto 0in;&quot;&gt;&lt;span style=&quot;font-family: &#39;Verdana&#39;,&#39;sans-serif&#39;;&quot;&gt;&lt;span style=&quot;color:#000080;&quot;&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;*****&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: rgb(51, 51, 51); font-family: &#39;Verdana&#39;,&#39;sans-serif&#39;;&quot;&gt;Suppose you have data in your table that represents the logical information of &quot;Yes&quot; and &quot;No&quot;&lt;/span&gt;&lt;/strong&gt;&lt;span style=&quot;color: rgb(51, 51, 51); font-family: &#39;Verdana&#39;,&#39;sans-serif&#39;;&quot;&gt; and you want to give the results of a query to someone who isn&#39;t working all day with computers. For such people, they may not know that a 1 is the logical representation of TRUE while a 0 represents FALSE. Sure, you can do this at the presentational layer. But what if someone comes to your desk, begging for immediate help? Here&#39;s a little trick to make BITs (or any other 0 and 1 data) look a bit more intuitive:&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;pre&gt;&lt;span style=&quot;font-size: 12pt; color: rgb(0, 51, 255);&quot;&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;CREATE TABLE MyBits &lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span style=&quot;font-size: 12pt; color: rgb(0, 51, 255);&quot;&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;(&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span style=&quot;font-size: 12pt; color: rgb(0, 51, 255);&quot;&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;id INT IDENTITY(1,1) PRIMARY KEY &lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span style=&quot;font-size: 12pt; color: rgb(0, 51, 255);&quot;&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;, bool BIT&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span style=&quot;font-size: 12pt; color: rgb(0, 51, 255);&quot;&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;)&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span style=&quot;font-size: 12pt; color: rgb(0, 51, 255);&quot;&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;GO&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span style=&quot;font-size: 12pt; color: rgb(0, 51, 255);&quot;&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;INSERT INTO MyBits&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span style=&quot;font-size: 12pt; color: rgb(0, 51, 255);&quot;&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;SELECT 0&lt;span style=&quot;&quot;&gt;  &lt;/span&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span style=&quot;font-size: 12pt; color: rgb(0, 51, 255);&quot;&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;UNION ALL &lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span style=&quot;font-size: 12pt; color: rgb(0, 51, 255);&quot;&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;SELECT 1&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span style=&quot;font-size: 12pt; color: rgb(0, 51, 255);&quot;&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;GO&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span style=&quot;font-size: 12pt; color: rgb(0, 51, 255);&quot;&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;SELECT &lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span style=&quot;font-size: 12pt; color: rgb(0, 51, 255);&quot;&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;id &lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span style=&quot;font-size: 12pt; color: rgb(0, 51, 255);&quot;&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;, bool &lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span style=&quot;font-size: 12pt; color: rgb(0, 51, 255);&quot;&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;, SUBSTRING(&#39;YesNo&#39;, 4 - 3 * bool, 3) as YesNo&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span style=&quot;font-size: 12pt; color: rgb(0, 51, 255);&quot;&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;FROM&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span style=&quot;font-size: 12pt; color: rgb(0, 51, 255);&quot;&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;MyBits&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span style=&quot;font-size: 12pt; color: rgb(0, 51, 255);&quot;&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;GO&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span style=&quot;font-size: 12pt; color: rgb(0, 51, 255);&quot;&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;DROP TABLE MyBits &lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span style=&quot;font-size: 12pt; color: rgb(0, 51, 255);&quot;&gt;&lt;o:p&gt;&lt;span style=&quot;font-size:85%;&quot;&gt; &lt;/span&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span style=&quot;font-size: 12pt; color: rgb(0, 51, 255);&quot;&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;id&lt;span style=&quot;&quot;&gt;          &lt;/span&gt;bool YesNo &lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span style=&quot;font-size: 12pt; color: rgb(0, 51, 255);&quot;&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;----------- ---- ----- &lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span style=&quot;font-size: 12pt; color: rgb(0, 51, 255);&quot;&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;1&lt;span style=&quot;&quot;&gt;           &lt;/span&gt;0&lt;span style=&quot;&quot;&gt;    &lt;/span&gt;No&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span style=&quot;font-size: 12pt; color: rgb(0, 51, 255);&quot;&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;2&lt;span style=&quot;&quot;&gt;           &lt;/span&gt;1&lt;span style=&quot;&quot;&gt;    &lt;/span&gt;Yes&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span style=&quot;font-size: 12pt; color: rgb(0, 51, 255);&quot;&gt;&lt;o:p&gt;&lt;span style=&quot;font-size:85%;&quot;&gt; &lt;/span&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre&gt;&lt;span style=&quot;font-size: 12pt; color: rgb(0, 51, 255);&quot;&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;(2 row(s) affected)&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt; &lt;span style=&quot;color: rgb(51, 51, 51); font-family: &#39;Verdana&#39;,&#39;sans-serif&#39;;&quot;&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;How does this work? The trick happens inside the SUBSTRING function. Precisely, when calculating the start value for the SUBSTRING. If our column &quot;bool&quot; contains a 0, the calculation looks like SUBSTRING(&#39;YesNo&#39;, 4 - 3 * 0, 3), which resolves to SUBSTRING(&#39;YesNo&#39;, 4, 3) and therefore, correctly returns &#39;No&#39;. We actually use here another feature of SUBSTRING. If the string is shorter than our requested length, SUBSTRING simply returns the shorter string without filling up the missing spaces. Finally, in case a 1 is in our &quot;bool&quot; column, the calculation goes like SUBSTRING(&#39;YesNo&#39;, 4 - 3 * 1, 4), which is SUBSTRING(&#39;YesNo, 1, 3) and that is &#39;Yes&#39;. [7.0, 2000, 2005] &lt;em&gt;&lt;span style=&quot;font-family: &#39;Verdana&#39;,&#39;sans-serif&#39;;&quot;&gt;Added 5-9-2005&lt;/span&gt;&lt;/em&gt;&lt;/span&gt;&lt;/span&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;octopus east java baker&lt;/div&gt;</description><link>http://scriptster.blogspot.com/2007/09/sql-server-transact-sql-general-tips.html</link><author>noreply@blogger.com (Octopus)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-2977499297091575918.post-6598498225064785910</guid><pubDate>Thu, 20 Sep 2007 07:17:00 +0000</pubDate><atom:updated>2007-09-20T00:17:57.527-07:00</atom:updated><title>Fedora Core 6 Tips and Tricks (v1.3)</title><description>&lt;p&gt;  This is based on my &lt;a href=&quot;http://www.gagme.com/greg/linux/fc5-tips.php&quot;&gt;Fedora Core 5 Tips and Tricks&lt;/a&gt; page.  This is in maintenance only mode since there is now a &lt;a href=&quot;http://www.gagme.com/greg/linux/f7-tips.php&quot;&gt;Fedora 7&lt;/a&gt; version of this guide in the works.  Recent changes are &lt;span class=&quot;HL&quot;&gt;highlighted in yellow&lt;/span&gt;. &lt;/p&gt;&lt;p&gt; I&#39;ve started to add x86_64 specific instructions below when they differ from traditional 32-bit instructions.  The biggest issue is with multimedia plug-ins which are still often available only in 32-bit versions. &lt;/p&gt;&lt;p&gt; &lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;http://www.gagme.com/greg/linux/fc6-tips.php#i586kernel&quot;&gt;Fix i586/i686 Kernel issue&lt;/a&gt;  &lt;/li&gt;&lt;li&gt;&lt;a href=&quot;http://www.gagme.com/greg/linux/fc6-tips.php#repos&quot;&gt;Add support for other repositories&lt;/a&gt;  &lt;/li&gt;&lt;li&gt;&lt;a href=&quot;http://www.gagme.com/greg/linux/fc6-tips.php#mp3&quot;&gt;Install MP3 plug-in&lt;/a&gt; &lt;/li&gt;&lt;li&gt;&lt;a href=&quot;http://www.gagme.com/greg/linux/fc6-tips.php#flash&quot;&gt;Install Macromedia Flash/Shockwave Plug-in&lt;/a&gt; &lt;/li&gt;&lt;li&gt;&lt;a href=&quot;http://www.gagme.com/greg/linux/fc6-tips.php#dvd&quot;&gt;Install DVD player&lt;/a&gt; &lt;/li&gt;&lt;li&gt;&lt;a href=&quot;http://www.gagme.com/greg/linux/fc6-tips.php#mplayer&quot;&gt;Install MPlayer Media Player&lt;/a&gt; &lt;/li&gt;&lt;li&gt;&lt;a href=&quot;http://www.gagme.com/greg/linux/fc6-tips.php#vlc&quot;&gt;Install VLC (VideoLAN Client)&lt;/a&gt; &lt;/li&gt;&lt;li&gt;&lt;a href=&quot;http://www.gagme.com/greg/linux/fc6-tips.php#rplayer&quot;&gt;Install RealPlayer 10 Media Player&lt;/a&gt; &lt;/li&gt;&lt;li&gt;&lt;a href=&quot;http://www.gagme.com/greg/linux/fc6-tips.php#java&quot;&gt;Install Java J2RE and Mozilla Plug-in&lt;/a&gt; &lt;/li&gt;&lt;li&gt;&lt;a href=&quot;http://www.gagme.com/greg/linux/fc6-tips.php#ntfs&quot;&gt;Install NTFS driver&lt;/a&gt; &lt;/li&gt;&lt;li&gt;&lt;a href=&quot;http://www.gagme.com/greg/linux/fc6-tips.php#ie&quot;&gt;Install Internet Explorer&lt;/a&gt; &lt;/li&gt;&lt;li&gt;&lt;a href=&quot;http://www.gagme.com/greg/linux/fc6-tips.php#oddsnends&quot;&gt;Install Other Odds and Ends&lt;/a&gt; &lt;/li&gt;&lt;li&gt;&lt;a href=&quot;http://www.gagme.com/greg/linux/fc6-tips.php#other&quot;&gt;Other Useful Resources&lt;/a&gt; &lt;/li&gt;&lt;/ul&gt;  &lt;hr width=&quot;100%&quot;&gt;  &lt;a href=&quot;http://www.savetheinternet.com/&quot; target=&quot;STI&quot;&gt;&lt;img src=&quot;http://www.savetheinternet.com/images/sti_button.gif&quot; title=&quot;Your help is needed NOW to help save the Internet from special interest groups&quot; align=&quot;right&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;a name=&quot;i586kernel&quot;&gt;&lt;h3&gt;Fix i586/i686 Kernel issue&lt;/h3&gt;&lt;/a&gt;  Under some circumstances the Fedora Core 6 installer (called Anaconda) will mistakenly install the i586 version of the Kernel rather than the more appropriate i686 version for Pentium 4 and newer 32-bit processors.  This is not a problem on x86_64 and non-Intel/AMD processors. &lt;p&gt; To find out if your system has this problem type the following command: &lt;/p&gt;&lt;pre&gt;$ rpm -qa --queryformat &quot;%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}\n&quot;|grep kernel|sort &lt;br /&gt;&lt;/pre&gt; If you have a Pentium 4 or newer processor and the kernel version ends in &lt;b&gt;i586&lt;/b&gt; then your system and affected and needs to be updated to function at it&#39;s best.  There are many ways described to do this on various forums but by far the easiest is the &lt;b&gt;Kernel Fix Script&lt;/b&gt; on the &lt;b&gt;Bugs/FC6Common&lt;/b&gt; site: &lt;blockquote&gt; &lt;a href=&quot;http://fedoraproject.org/wiki/Bugs/FC6Common#head-e0676100ebd965b92fbaa7111097983a3822f143&quot; target=&quot;_blank&quot;&gt;Fedora Core 6 - Common Bugs and Known Issues&lt;/a&gt; &lt;/blockquote&gt; Script down and find the script.  Download it to your hard drive and run it as root: &lt;pre&gt;# mkdir /tmp/kernel-fix&lt;br /&gt;# cd /tmp/kernel-fix&lt;br /&gt;# sh kernel-fix.sh&lt;br /&gt;&lt;/pre&gt; Then just follow the prompts and it will update your installed kernel. Using kernel-fix.sh sould be with care as it runs all the *.rpm at current directory (see line 32).     &lt;hr width=&quot;100%&quot;&gt; &lt;a name=&quot;repos&quot;&gt;&lt;h3&gt;Add support for other repositories&lt;/h3&gt;&lt;/a&gt;  Fedora core 6 has one major problem where on some systems it installs the i586 version of the kernel instead of i686.  What this means is that those systems will be a little slower and will lack CPU frequency scaling.  If you are running an i686 based system you can force the installation of the correct kernel by booting the installer with the following command: &lt;pre&gt;linux i686&lt;br /&gt;&lt;/pre&gt; &lt;p&gt; Fedora comes with a ton of software but there are still plenty of packages of interest to most users that are not included for a variety of reasons. This is where you find the MP3 plug-in and a ton of other packages. &lt;/p&gt;&lt;p&gt; These instructions can vary depending on 32bit or 64bit architecture.  If there is a difference it will be noted. If you don&#39;t know which architecture you&#39;re running you can run the following command: &lt;/p&gt;&lt;pre&gt;$ uname -m&lt;br /&gt;x86_64&lt;br /&gt;&lt;i&gt;...or...&lt;/i&gt;&lt;br /&gt;i686&lt;br /&gt;&lt;/pre&gt; I&#39;m still working on the 64 bit specific instructions so your feedback is very important.  &lt;p&gt; Before you add repositories it&#39;s probably a good idea to make sure your system is fully updated first. It&#39;s still early but right now the &lt;b&gt;Livna&lt;/b&gt; and &lt;b&gt;freshrpms&lt;/b&gt; repositories seems to be the most useful. The easiest way to get started is to install the &lt;span class=&quot;code&quot;&gt;freshrpms-release&lt;/span&gt; packages: &lt;/p&gt;&lt;pre&gt;&lt;b&gt;Both 32 and 64 bits:&lt;/b&gt;&lt;br /&gt;# rpm -ihv http://ayo.freshrpms.net/fedora/linux/6/i386/RPMS.freshrpms/freshrpms-release-1.1-1.fc.noarch.rpm&lt;br /&gt;&lt;b&gt;32 bit version:&lt;/b&gt;&lt;br /&gt;# rpm -ihv http://rpm.livna.org/fedora/6/i386/livna-release-6-1.noarch.rpm&lt;br /&gt;&lt;b&gt;64 bit version:&lt;/b&gt;&lt;br /&gt;# rpm -ihv http://rpm.livna.org/fedora/6/x86_64/livna-release-6-1.noarch.rpm&lt;br /&gt;&lt;/pre&gt;  To automatically install/update the Macromedia Flash version 9.0 plug-in copy &lt;a href=&quot;http://macromedia.mplug.org/macromedia-i386.repo&quot;&gt;This File&lt;/a&gt; to your &lt;span class=&quot;code&quot;&gt;/etc/yum.repos.d&lt;/span&gt; directory.  You can browse the packages available there at &lt;a href=&quot;http://rpm.livna.org/fedora/6/i386/&quot;&gt;http://rpm.livna.org/fedora/6/i386/&lt;/a&gt; and &lt;a href=&quot;http://zod.freshrpms.net/&quot;&gt;http://zod.freshrpms.net/&lt;/a&gt;. &lt;p&gt;   &lt;/p&gt;&lt;hr width=&quot;100%&quot;&gt; &lt;a name=&quot;mp3&quot;&gt;&lt;h3&gt;Install MP3 Plug-in&lt;/h3&gt;&lt;/a&gt;   Since you&#39;ve been following along this next step is about as easy as it gets.  Just use &lt;a style=&quot;color: black; background-color: rgb(230, 230, 230);&quot;&gt;yum&lt;/a&gt;  to automatically install the MP3 plug-ins for &lt;b&gt;xmms&lt;/b&gt; and &lt;b&gt;Rhythmbox&lt;/b&gt; like this: &lt;pre&gt;# yum -y install xmms xmms-mp3 xmms-faad2 gstreamer-plugins-ugly libmad libid3tag&lt;br /&gt;&lt;/pre&gt; While you&#39;re here you might as well install my personal favorite (this week at least) music player &lt;b&gt;Banshee&lt;/b&gt;: &lt;pre&gt;# yum -y install banshee&lt;br /&gt;&lt;/pre&gt;  The &lt;a style=&quot;color: black; background-color: rgb(230, 230, 230);&quot;&gt;-y&lt;/a&gt;  flag is to automatically answer yes to any question.  If you want to be able to say no you can ignore that flag. &lt;p&gt; While you&#39;re there I highly recommend the &lt;a style=&quot;color: black; background-color: rgb(230, 230, 230);&quot;&gt;grip&lt;/a&gt; CD ripper which supports both MP3 and Ogg formats.  Once again installation is quite simple: &lt;/p&gt;&lt;pre&gt;# yum -y install grip&lt;br /&gt;&lt;/pre&gt;  &lt;hr width=&quot;100%&quot;&gt;  &lt;a name=&quot;flash&quot;&gt;&lt;h3&gt;Install Macromedia Flash/Shockwave plug-in&lt;/h3&gt;&lt;/a&gt;  &lt;b&gt;Flash Plug-in 9.0&lt;/b&gt;&lt;br /&gt;If you set up the repositories correctly above you should just need to do this to install the Flash plug-in version 9.0: &lt;pre&gt;# yum -y install flash-plugin&lt;br /&gt;&lt;/pre&gt; You can get more information about this plug-in at &lt;a href=&quot;http://macromedia.mplug.org/&quot;&gt;http://macromedia.mplug.org/&lt;/a&gt;. Before the plug-in gets installed you&#39;ll need to agree to the terms of the license. &lt;p&gt; &lt;b&gt;Special 64-bit instructions:&lt;/b&gt;&lt;br /&gt;Now the problem with 64 bit, even on Windows, is that most plug-ins are still for some reason only available in a 32 bit version.  This is a problem because a 64 bit version of Firefox can only use 64 bit plugins.  There are several ways to solve this but by far the easiest is to just force the use of the 32-bit Firebox.  Both versions are installed by default, you just need to make a little change to make sure only the 32-bit version gets run. &lt;/p&gt;&lt;p&gt; &lt;span class=&quot;HL&quot;&gt;As of &lt;b&gt;firefox-1.5.0.10-5.fc6&lt;/b&gt; the method of selecting the 32-bit version has been simplified.  Now you simply create a file called &lt;span class=&quot;code&quot;&gt;/etc/sysconfig/firefox-arch&lt;/span&gt; containing the following lines: &lt;/span&gt;&lt;/p&gt;&lt;pre class=&quot;HL&quot;&gt;&lt;span class=&quot;HL&quot;&gt;MOZ_LIB_DIR=&quot;/usr/lib&quot;&lt;br /&gt;SECONDARY_LIB_DIR=&quot;/usr/lib64&quot;&lt;br /&gt;&lt;/span&gt;&lt;/pre&gt;  &lt;p&gt; &lt;span class=&quot;HL&quot;&gt;The remainder of these instructions are only for people who have not updated lately and still have an older version of &lt;b&gt;Firefox&lt;/b&gt;.  These instructions will go away soon: &lt;/span&gt; &lt;/p&gt;&lt;p&gt; Edit the file &lt;span class=&quot;code&quot;&gt;/usr/bin/firefox&lt;/span&gt; as root and go down to about line 40 and comment out the following code: &lt;/p&gt;&lt;pre&gt;# Force 32 bit version&lt;br /&gt;#if [ -x &quot;/usr/lib64/firefox-1.5.0.8/firefox-bin&quot; ]&lt;br /&gt;#then&lt;br /&gt;#  MOZ_LIB_DIR=&quot;/usr/lib64&quot;&lt;br /&gt;#fi&lt;br /&gt;&lt;/pre&gt; Then when you restart Firefox you&#39;ll be running the 32 bit version and the plug-ins you installed above will work just fine.  &lt;hr width=&quot;100%&quot;&gt; &lt;a name=&quot;dvd&quot;&gt;&lt;h3&gt;Install DVD player&lt;/h3&gt;&lt;/a&gt;  Currently I find the DVD player that works best is the &lt;b&gt;Xine Multimedia Player&lt;/b&gt; which is found in the &lt;b&gt;Livna&lt;/b&gt; repository so installing it is just this simple: &lt;pre&gt;# yum -y install xine xine-lib xine-skins xine-lib-extras-nonfree libdvdcss&lt;br /&gt;&lt;/pre&gt; This will install the &lt;b&gt;xine&lt;/b&gt; DVD/VCD/CD player. Now to get &lt;b&gt;xine&lt;/b&gt; to automatically play a DVD upon insertion instead of the &lt;b&gt;Totem&lt;/b&gt; player which can&#39;t actually play DVDs, you can simply use the &lt;span class=&quot;code&quot;&gt;gconftool-2&lt;/span&gt; utility as follows: &lt;pre&gt;$ gconftool-2 --set /desktop/gnome/volume_manager/autoplay_dvd_command \&lt;br /&gt; &#39;xine --auto-play --auto-scan dvd&#39; --type=&#39;string&#39;&lt;br /&gt;&lt;/pre&gt;   &lt;hr width=&quot;100%&quot;&gt;  &lt;a name=&quot;mplayer&quot;&gt;&lt;h3&gt;Install MPlayer Media Player&lt;/h3&gt;&lt;/a&gt;  At some point you&#39;re probably going to want to play a QuickTime, AVI or ASF file so you&#39;ll want the &lt;b&gt;MPlayer&lt;/b&gt; media player.  Fortunately with the &lt;b&gt;FreshRpms&lt;/b&gt; repositories it&#39;s also very easy to download and install.  Once again there are conflicts between the &lt;b&gt;Livna&lt;/b&gt; and &lt;b&gt;FreshRpms&lt;/b&gt; repositories and you&#39;ll have to disable one of them. &lt;p&gt; To prevent potential problems of updates in the &lt;b&gt;Livna&lt;/b&gt; repository from messing up the &lt;a style=&quot;color: black; background-color: rgb(230, 230, 230);&quot;&gt;mplayer&lt;/a&gt;  and &lt;a style=&quot;color: black; background-color: rgb(230, 230, 230);&quot;&gt;mencoder&lt;/a&gt;  packages add the following line highligted in bold to the file &lt;a style=&quot;color: black; background-color: rgb(230, 230, 230);&quot;&gt;/etc/yum.repos.d/livna.repo&lt;/a&gt; : &lt;/p&gt;&lt;pre&gt;gpgcheck=1&lt;br /&gt;gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-livna&lt;br /&gt;&lt;b&gt;exclude=mplayer* mencoder* &lt;span class=&quot;HL&quot;&gt;ffmpeg*&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;[livna-debuginfo]&lt;br /&gt;&lt;/pre&gt; Then you can go ahead and install &lt;a style=&quot;color: black; background-color: rgb(230, 230, 230);&quot;&gt;mplayer&lt;/a&gt; and all it&#39;s dependencies: &lt;pre&gt;# yum -y install mplayer mplayer-skins mplayer-fonts mplayerplug-in&lt;br /&gt;&lt;/pre&gt; This command line will download the whole kit and kaboodle. that if you want to play content from a command line that you use the &lt;a style=&quot;color: black; background-color: rgb(230, 230, 230);&quot;&gt;gmplayer&lt;/a&gt;  version which will include a skin-able control panel. This will install the plug-in to play a wide variety of media within your browser window. Restart your web browser after that whole mess is done installing and you&#39;ll also have a plug-in for Mozilla so you can play embedded content. While you&#39;re at it be sure to configure &lt;b&gt;mplayer&lt;/b&gt; to use the ALSA sound system rather than the default.  It just works better. Edit the file &lt;a style=&quot;color: black; background-color: rgb(230, 230, 230);&quot;&gt;~/.mplayer/config&lt;/a&gt; and add the following line: &lt;pre&gt;ao=alsa&lt;br /&gt;&lt;/pre&gt; &lt;p&gt; &lt;b&gt;Special 64-bit instructions:&lt;/b&gt;&lt;br /&gt;This installs the 64-bit version of everything but because your other plug-ins are 32-bits you need to run the 32-bit version of Firefox, which won&#39;t be able to use the 64-bit version of the plug-in you just installed. The plug-in can use the 64-bit version of the mplayer application just fine so all you need to do then is to install the 32-bit mplayerplug-in plus a dependency it requires. If you know of any easier way to do this please let me know below. &lt;/p&gt;&lt;pre&gt;# rpm -ihv http://ftp.ndlug.nd.edu/pub/fedora/linux/core/6/i386/os/Fedora/RPMS/libXpm-3.5.5-3.i386.rpm&lt;br /&gt;# rpm -ihv http://ftp.freshrpms.net/pub/freshrpms/fedora/linux/6/mplayerplug-in/mplayerplug-in-3.31-2.fc6.i386.rpm&lt;br /&gt;&lt;/pre&gt;  And finally you&#39;ll probably also want some additional codecs to play all that proprietary video that seems to have infected the Internet. Go to the &lt;a href=&quot;http://www.mplayerhq.hu/design7/dload.html&quot;&gt;MPlayer Download&lt;/a&gt; page and download the essential &lt;b&gt;Binaries Codec Package&lt;/b&gt;. You&#39;ll need to install those files in &lt;span class=&quot;code&quot;&gt;/usr/local/lib/win32&lt;/span&gt;.  Here are the steps.  Remember the exact file names may change at some point. &lt;pre&gt;# gtar xjvf essential-20061022.tar.bz2&lt;br /&gt;# mkdir /usr/local/lib/win32&lt;br /&gt;# mv essential-20061022/* /usr/local/lib/win32&lt;br /&gt;&lt;/pre&gt;  &lt;hr width=&quot;100%&quot;&gt;  &lt;a name=&quot;vlc&quot;&gt;&lt;h3&gt;Install VLC (VideoLAN Client)&lt;/h3&gt;&lt;/a&gt;  Multimedia can be the achilles heel of Linux, but with just a little work you should be able to play just about anything your friends can. Besides Mplayer the other great video player is called VLC.  It too is trivially easy to install once you have your repositories set up: &lt;pre&gt;# yum -y install videolan-client&lt;br /&gt;&lt;/pre&gt; Once the client and a zillion dependencies get installed you can play a huge variety of video formats easy with the command &lt;a style=&quot;color: black; background-color: rgb(230, 230, 230);&quot;&gt;vlc&lt;/a&gt;   &lt;hr width=&quot;100%&quot;&gt;  &lt;a name=&quot;rplayer&quot;&gt;&lt;h3&gt;Install RealPlayer 10 Media Player&lt;/h3&gt;&lt;/a&gt;  If you have a better way of installing a Real Medial player please let me know if in the comments section below.  Thanks to Chandra Shekhar for this great tip for making RealPlayer actually use ALSA instead of OSS. I&#39;ve incorporated the changes into the guide below but here is a link to the original document. &lt;blockquote&gt; &lt;a href=&quot;http://docs.google.com/View?docid=ddt5bn9t_4c9238p&quot; target=&quot;_blank&quot;&gt;http://docs.google.com/View?docid=ddt5bn9t_4c9238p&lt;/a&gt; &lt;/blockquote&gt; &lt;p&gt; Before you install the play you&#39;ll need to make sure the &lt;span class=&quot;code&quot;&gt;compat-libstdc++-33&lt;/span&gt; module is installed. Download the &lt;b&gt;RealPlayer10&lt;/b&gt; package from the following location:  &lt;/p&gt;&lt;blockquote&gt; &lt;a href=&quot;http://www.real.com/realcom/R?href=http%3A%2F%2Fforms.real.com%2Freal%2Fplayer%2Fdownload.html%3Ff%3Dunix%2FRealPlayer10GOLD.rpm%26product%3Dplayerplus%26system%3Dlinux&amp;amp;pageid=linuxHomePage&amp;amp;pageregion=advanced_install&amp;amp;src=realhome_linux_0_2_1_0_0_3&amp;amp;pcode=rn&amp;amp;opage=realhome_linux&quot;&gt;RealPlayer10GOLD.rpm&lt;/a&gt;&lt;br /&gt;&lt;/blockquote&gt;   First install the dependencies. &lt;pre&gt;&lt;b&gt;32 bit version&lt;/b&gt;&lt;br /&gt;# yum -y install compat-libstdc++-33 alsa-oss&lt;br /&gt;&lt;b&gt;64 bit version&lt;/b&gt;  There really MUST be an easier way!&lt;br /&gt;# rpm -ihv ftp://fedora.cat.pdx.edu/linux/extras/6/i386/alsa-oss-1.0.12-3.fc6.i386.rpm&lt;br /&gt;&lt;/pre&gt; Then install the RPM: &lt;pre&gt;# rpm -ihv RealPlayer10GOLD.rpm&lt;br /&gt;&lt;/pre&gt; The other thing you&#39;ll need to do is prevent the &lt;php&gt;mplayerplug-in  you installed above from trying to handle Real Media. I don&#39;t know why it&#39;s included because it almost never works correctly. The easiest way to disable it is to remove the appropriate plugin files: &lt;/php&gt;&lt;pre&gt;# cd /usr/lib/mozilla/plugins&lt;br /&gt;# rm mplayerplug-in-rm.so&lt;br /&gt;&lt;/pre&gt;  Then whenever you want to view something just use &lt;a style=&quot;color: black; background-color: rgb(230, 230, 230);&quot;&gt;/usr/bin/realplay&lt;/a&gt; .  Here is a link to a cute &lt;a href=&quot;http://www.gagme.com/greg/diving/dive202-256k.ram&quot;&gt;test video&lt;/a&gt; to make sure it&#39;s working for you. &lt;p&gt; If audio is working but you have a black screen then it&#39;s possible your video card doesn&#39;t support XVideo.  You can turn it off by clicking on &lt;a style=&quot;color: black; background-color: rgb(230, 230, 230);&quot;&gt;Tools&lt;/a&gt;  -&gt; &lt;a style=&quot;color: black; background-color: rgb(230, 230, 230);&quot;&gt;Preferences&lt;/a&gt; then choose the Hardware tab and disable &lt;a style=&quot;color: black; background-color: rgb(230, 230, 230);&quot;&gt;Use XVideo&lt;/a&gt; . &lt;/p&gt;&lt;p&gt; If the video doesn&#39;t play properly the first thing to check is to make sure you&#39;re not running &lt;b&gt;SElinux&lt;/b&gt;, it seems to prevent the RealPlayer from getting access to the drivers.  I currently run with &lt;b&gt;SElinux&lt;/b&gt;  disabled but I recommend you run it in the &lt;b&gt;Targeted&lt;/b&gt; mode rather than the most secure mode. &lt;/p&gt;&lt;p&gt; Now a bit of a tricky part.  You&#39;ll need to edit the executable &lt;span class=&quot;code&quot;&gt;/usr/bin/realplay&lt;/span&gt; as root and locate the section below around line 56.  Then add the code that&#39;s highlighted and save the file  back. &lt;/p&gt;&lt;pre&gt; .&lt;br /&gt; .&lt;br /&gt;   export HELIX_LIBS&lt;br /&gt;fi&lt;br /&gt;&lt;br /&gt;LD_PRELOAD=&quot;$LDPRELOAD:/usr/lib/libaoss.so.0.0.0&quot;&lt;br /&gt;export LD_PRELOAD&lt;br /&gt;  &lt;br /&gt;# See if LD_PRELOAD contains any of the sound server libs. If so, remove them.&lt;br /&gt;LD_PRELOAD=`echo $LD_PRELOAD | sed -e &#39;s/\([^:]*libesd[^:]*\|[^:]*libarts[^:]*\):\?//g&#39;`&lt;br /&gt; .&lt;br /&gt; .&lt;br /&gt;&lt;/pre&gt; &lt;p&gt; After you&#39;ve run it the first time and gone through the configuration screens edit the &lt;a style=&quot;color: black; background-color: rgb(230, 230, 230);&quot;&gt;~/.realplayerrc&lt;/a&gt;  file and add the following line in the &lt;a style=&quot;color: black; background-color: rgb(230, 230, 230);&quot;&gt;[helix]&lt;/a&gt;  section of the configuration: &lt;/p&gt;&lt;pre&gt;[helix]&lt;br /&gt;&lt;b&gt;SoundDriver=2&lt;/b&gt;&lt;br /&gt;       .&lt;br /&gt;       .&lt;br /&gt;&lt;/pre&gt; For some reason on my system RealPlayer uses the the old and virtually obsolete OSS sound driver.  The line above tells it to use the newer ALSA sound driver instead.   &lt;hr width=&quot;100%&quot;&gt;  &lt;a name=&quot;java&quot;&gt;&lt;h3&gt;Install Java J2RE and Mozilla Plug-in&lt;/h3&gt;&lt;/a&gt;  It&#39;s also very handy to have the Java run-time environment available and most importantly a Mozilla plug-in so you can view dynamic content. It&#39;s unfortunate that Mozilla will actually crash if you go to a site containing Java and you don&#39;t have the plug-in installed. &lt;p&gt; For now there is no easy way to do this but I found the following instructions on &lt;a href=&quot;http://forums.fedoraforum.org/showthread.php?t=59067&quot;&gt;FedoraForums.org&lt;/a&gt;. Basically, start by downloading the &lt;b&gt;Java Runtime Environment (JRE) 5.0 Update 9&lt;/b&gt; (at the time I wrote this) from &lt;a href=&quot;http://java.sun.com/j2se/1.5.0/download.jsp&quot;&gt;Sun.com&lt;/a&gt;. You&#39;ll want to grab the &lt;b&gt;Linux RPM in self-extracting&lt;/b&gt; file. Then you want to install it with: &lt;/p&gt;&lt;pre&gt;# sh ./jre-1_5_0_09-linux-i586-rpm.bin&lt;br /&gt;&lt;/pre&gt; &lt;p&gt; Then you&#39;ll probably want to enable &lt;b&gt;Java Plug-ins&lt;/b&gt; and here once again there is no easy way: &lt;/p&gt;&lt;pre&gt;# ln -s /usr/java/jre1.5.0_09/plugin/i386/ns7/libjavaplugin_oji.so /usr/lib/mozilla/plugins&lt;br /&gt;&lt;/pre&gt; And finally you&#39;ll need to tell &lt;b&gt;Fedora&lt;/b&gt; that you wish to use this version of &lt;b&gt;Java&lt;/b&gt; as the preferred interpreter rather than the Open Source version that&#39;s installed by default.  You&#39;ll of course need to adjust the full pathname if you install a newer version of the &lt;b&gt;jre&lt;/b&gt; than the one in this example: &lt;pre&gt;# /usr/sbin/alternatives --install /usr/bin/java java /usr/java/jre1.5.0_09/bin/java 1509&lt;br /&gt;# java -version&lt;br /&gt;java version &quot;1.5.0_09&quot;&lt;br /&gt;Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_09-b05)&lt;br /&gt;Java HotSpot(TM) Client VM (build 1.5.0_09-b05, mixed mode, sharing)&lt;br /&gt;&lt;/pre&gt; If you know of an easier way please post it to the &lt;b&gt;Comments&lt;/b&gt; section below.   &lt;hr width=&quot;100%&quot;&gt;  &lt;a name=&quot;ntfs&quot;&gt;&lt;h3&gt;Install NTFS driver&lt;/h3&gt;&lt;/a&gt;  With repositories like &lt;b&gt;Fedora Extras&lt;/b&gt; it&#39;s now very easy to add NTFS support to Fedora: &lt;pre&gt;# yum -y install ntfs-3g&lt;br /&gt;&lt;/pre&gt; Then you can simply mount NTFS file systems using the option &lt;span class=&quot;code&quot;&gt;-t ntfs-3g&lt;/span&gt;.  You can find more detailed information about this driver at &lt;a href=&quot;http://www.ntfs-3g.org/&quot; target=&quot;_blank&quot;&gt;http://www.ntfs-3g.org/&lt;/a&gt;    &lt;hr width=&quot;100%&quot;&gt;  &lt;a name=&quot;ie&quot;&gt;&lt;h3&gt;Install Internet Explorer&lt;/h3&gt;&lt;/a&gt;  I know what you&#39;re saying, why would I ever want Internet Explorer installed on my perfectly good Linux system?  If you don&#39;t have your own answer to that question, feel free to just skip this section.  For everyone else, it&#39;s actually quite easy thanks to some very handy scripts from &lt;a href=&quot;http://www.tatanka.com.br/ies4linux/index-en.html&quot;&gt;IEs4Linux&lt;/a&gt;. Before you start you&#39;ll need to make sure you have &lt;span class=&quot;code&quot;&gt;wine&lt;/span&gt; and &lt;span class=&quot;code&quot;&gt;cabextract&lt;/span&gt; installed: &lt;pre&gt;# yum -y install wine cabextract&lt;br /&gt;&lt;/pre&gt; Then just &lt;a href=&quot;http://www.tatanka.com.br/ies4linux/download.html&quot;&gt;download the latest script&lt;/a&gt;, extract and run it.  The example below is based on version &lt;b&gt;2.0.5&lt;/b&gt;, just adjust the version number as necessary.  Please note that you will want to install and run this as your own user, &lt;b&gt;NOT as root&lt;/b&gt;.  I used the defaults except that I installed all the versions of IE.  I do some web development and I always find myself needing to resolve some goofy incompatibilites with older versions of IE. &lt;pre&gt;$ gtar xzvf ies4linux-2.0.5.tar.gz&lt;br /&gt;$ cd ies4linux-2.0.5&lt;br /&gt;$ ./ies4linux&lt;br /&gt;Welcome, greg! I&#39;m IEs4Linux.&lt;br /&gt;I can install IE 6, 5.5 and 5.0 for you easily and quickly.&lt;br /&gt;You are just four &#39;enter&#39;s away from your IEs.&lt;br /&gt;&lt;br /&gt;I&#39;ll ask you some questions now. Just answer y or n (default answer is the bold one)&lt;br /&gt;&lt;br /&gt;IE 6 will be installed automatically.&lt;br /&gt;Do you want to install IE 5.5 SP2 too? [ y / n ] &lt;b&gt;y&lt;/b&gt;&lt;br /&gt; .&lt;br /&gt; .&lt;br /&gt; .&lt;br /&gt;IEs 4 Linux installations finished!&lt;br /&gt;&lt;br /&gt;To run your IEs, type:&lt;br /&gt;ie6&lt;br /&gt;ie55&lt;br /&gt;ie5&lt;br /&gt;&lt;/pre&gt;  &lt;p&gt; You can read more about this feature on my &lt;a href=&quot;http://www.gagme.com/greg/linux/activex-linux.php&quot;&gt;Internet Explorer with ActiveX on Linux&lt;/a&gt; page.  It goes into a little more detail about using IE on Linux.  &lt;/p&gt;&lt;hr width=&quot;100%&quot;&gt;  &lt;a name=&quot;oddsnends&quot;&gt;&lt;h3&gt;Install Other Odds and Ends&lt;/h3&gt;&lt;/a&gt;  &lt;h4&gt;Add MS TrueType Fonts (TTF)&lt;/h4&gt; Many people will find it handy to have MS TrueType fonts available to make sure many websites render correctly.  You can download the latest RPM from &lt;a href=&quot;http://www.mjmwired.net/resources/mjm-fedora-fc5.html#ttf&quot;&gt;http://www.mjmwired.net/resources/mjm-fedora-fc5.html#ttf&lt;/a&gt; and install it as follows: &lt;pre&gt;#  wget --referer=http://www.mjmwired.net/resources/mjm-fedora-fc6.html \&lt;br /&gt;   http://www.mjmwired.net/resources/files/msttcorefonts-2.0-1.noarch.rpm&lt;br /&gt;# rpm -ihv msttcorefonts-2.0-1.noarch.rpm&lt;br /&gt;# service xfs restart&lt;br /&gt;&lt;/pre&gt;  &lt;h4&gt;Turn off the ANNOYING Spatial Nautilus Behavior&lt;/h4&gt; I don&#39;t know if it&#39;s the worst feature of Fedora but it&#39;s definitely in the top 5. You can get the old more sane behavior by bringing up &lt;b&gt;nautilus&lt;/b&gt; then choose &lt;b&gt;Edit&lt;/b&gt; -&gt; &lt;b&gt;Preferences&lt;/b&gt; then select the &lt;b&gt;Behavior&lt;/b&gt; tab. Near the top find the option for &lt;b&gt;Always open in browser windows&lt;/b&gt; and make sure it is checked.  &lt;h4&gt;Other Handy Utilities&lt;/h4&gt;  Here are a few other tools that aren&#39;t installed by default but a lot of people find handy:  &lt;pre&gt;# yum -y install bittorrent-gui gnomebaker testdisk thunderbird \&lt;br /&gt; audacity-nonfree screen cups-pdf&lt;br /&gt;&lt;/pre&gt; &lt;blockquote&gt; &lt;b&gt;audacity-nonfree&lt;/b&gt; - A version of the excellent Audacity sound editor which includes MP3 support &lt;b&gt;bittorrent-gui&lt;/b&gt; - Simple Gnome based BitTorrent client&lt;br /&gt;&lt;b&gt;cups-pdf&lt;/b&gt; - Add-on to CUPS which creates a PDF Printer which you can use to print any document in PDF format. The file is written to your Desktop.&lt;br /&gt;&lt;b&gt;gnomebaker&lt;/b&gt; - GTK based CD/DVD burning utility&lt;br /&gt;&lt;b&gt;screen&lt;/b&gt; - If you do a lot with the command line you&#39;ll find screen invaluable&lt;br /&gt;&lt;b&gt;testdisk&lt;/b&gt; - Two command line utilities to recover lost partitions and undelete files on FAT filesystems. VERY handy for undeleting files on flash memory cards.&lt;br /&gt;&lt;b&gt;thunderbird&lt;/b&gt; - Excellent E-mail client that complements Firefox &lt;/blockquote&gt;   &lt;hr width=&quot;100%&quot;&gt;  &lt;a name=&quot;other&quot;&gt;&lt;h3&gt;Other Useful Resources&lt;/h3&gt;&lt;/a&gt; I&#39;ve tried to not just copy other people&#39;s tips so I&#39;ve included a list of other people&#39;s tips and tricks I&#39;ve found to be useful.  There should be little or no overlap.   &lt;a href=&quot;http://www.fedoraforum.org/&quot; target=&quot;_BLANK&quot;&gt;&lt;b&gt;FedoraForum - Linux Support Community&lt;/b&gt;&lt;/a&gt; - This is now the official way to get community support of the Fedora Linux system.  There is no official Red Hat mailing list for any version of Fedora any more. &lt;p&gt; &lt;a href=&quot;http://www.mjmwired.net/resources/mjm-fedora-fc6.shtml&quot; target=&quot;_BLANK&quot;&gt;&lt;b&gt;Mauriat Miranda&#39;s FC6 Installation Guide&lt;/b&gt;&lt;/a&gt; - Great guide that goes into more depth of selecting options during the installation process.  This is also the source of the MS fonts RPM. &lt;/p&gt;&lt;p&gt; &lt;a href=&quot;http://stanton-finley.net/fedora_core_5_installation_notes.html&quot; target=&quot;_BLANK&quot;&gt;&lt;b&gt;Fedora Core 5 Linux Installation Notes&lt;/b&gt;&lt;/a&gt; - Another great Fedora installation guide.  This guide goes into some server related features rather than just desktop features. &lt;/p&gt;&lt;p&gt; &lt;a href=&quot;http://www.gurulabs.com/goodies/Using_Linux_and_Bluetooth_DUN_with_the_Treo650.php&quot; target=&quot;_BLANK&quot;&gt;&lt;b&gt;Using Linux and Bluetooth DUN on the Treo 650&lt;/b&gt;&lt;/a&gt; - A very nice guide to using a Treo 650 phone as a modem with your Linux based PC.  It works great for me with one change.  Do NOT uncomment the line &lt;a style=&quot;color: black; background-color: rgb(230, 230, 230);&quot;&gt;encrypt enable;&lt;/a&gt;  as it just won&#39;t work for me with encryption enabled with a D-Link DBT-120 and a Treo 650 phone. &lt;/p&gt;&lt;p&gt; &lt;a href=&quot;http://tldp.org/HOWTO/Fedora-Multimedia-Installation-HOWTO/index.html&quot; target=&quot;_BLANK&quot;&gt;&lt;b&gt;Fedora Multimedia Installation HOWTO&lt;/b&gt;&lt;/a&gt; - I discovered this great resource after I wrote this.  This document goes into more detail than mine so it&#39;s a great resource. &lt;/p&gt;&lt;p&gt; &lt;a href=&quot;http://www.fedorafaq.org/&quot; target=&quot;_BLANK&quot;&gt;&lt;b&gt;The Unofficial Fedora FAQ&lt;/b&gt;&lt;/a&gt; - Another great guide that should answer most general questions about Fedora. Fedora Core 5 doesn&#39;t seem to be addressed there yet but most answers are the same for both FC4 and FC5. &lt;/p&gt;&lt;p&gt; &lt;a href=&quot;http://www.fedoraserver.org/index.php?option=com_content&amp;amp;task=view&amp;amp;id=69&amp;amp;Itemid=38&quot; target=&quot;_BLANK&quot;&gt;&lt;b&gt;This Fedora Core 6 Tips &amp;amp; Tricks translated into Italian&lt;/b&gt;&lt;/a&gt; - Thanks to Guido for translating this guide into Italian.  Please contact me if you wish to translate this guide into other languages. &lt;/p&gt;&lt;p&gt; &lt;a href=&quot;http://easylinux.info/wiki/Fedora_fc5&quot; target=&quot;_BLANK&quot;&gt;&lt;b&gt;Fedora fc5 on EasyLinux.info&lt;/b&gt;&lt;/a&gt; - Yet another guide.  The thing I love about Linux is that you can solve any problem a number of different ways.  That includes these tips guides, everyone has a different way.  Different strokes for different folks. &lt;/p&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;octopus east java baker&lt;/div&gt;</description><link>http://scriptster.blogspot.com/2007/09/fedora-core-6-tips-and-tricks-v13.html</link><author>noreply@blogger.com (Octopus)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-2977499297091575918.post-8138990528509208899</guid><pubDate>Wed, 19 Sep 2007 07:43:00 +0000</pubDate><atom:updated>2007-09-19T00:48:04.652-07:00</atom:updated><title>Tip/Trick: Optimizing ASP.NET 2.0 Web Project Build Performance with VS 2005</title><description>&lt;p&gt;&lt;span style=&quot;;font-family:arial;font-size:85%;&quot;  &gt;This posts covers how to best optimize the build performance with Visual Studio 2005 when using web projects.  If you are experiencing slow builds or want to learn how to speed them up please read on.&lt;/span&gt;&lt;/p&gt;&lt;span style=&quot;;font-family:arial;font-size:85%;&quot;  &gt; &lt;/span&gt;&lt;p&gt;&lt;span style=&quot;;font-family:arial;font-size:85%;&quot;  &gt;&lt;strong&gt;Quick Background on VS 2005 Web Site Project and VS 2005 Web Application Project options&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;span style=&quot;;font-family:arial;font-size:85%;&quot;  &gt; &lt;/span&gt;&lt;p&gt;&lt;span style=&quot;;font-family:arial;font-size:85%;&quot;  &gt;&lt;img src=&quot;http://webproject.scottgu.com/intro.png&quot; align=&quot;right&quot; /&gt; VS 2005 supports two project-model options: &lt;a href=&quot;http://weblogs.asp.net/scottgu/archive/2005/08/21/423201.aspx&quot; target=&quot;_blank&quot;&gt;VS 2005 Web Site Projects&lt;/a&gt; and &lt;a href=&quot;http://weblogs.asp.net/scottgu/archive/2006/05/08/VS-2005-Web-Application-Project-V1.0-Released.aspx&quot; target=&quot;_blank&quot;&gt;VS 2005 Web Application Projects&lt;/a&gt;.  &lt;/span&gt;&lt;/p&gt;&lt;span style=&quot;;font-family:arial;font-size:85%;&quot;  &gt; &lt;/span&gt;&lt;p&gt;&lt;span style=&quot;;font-family:arial;font-size:85%;&quot;  &gt;VS 2005 Web Site Projects were built-in with the initial VS 2005 release, and provide a project-less based model for doing web development that uses that same dynamic compilation system that ASP.NET 2.0 uses at runtime.  VS 2005 Web Application Projects were released as a fully supported download earlier this spring, and provide a project model that uses a MSBuild based build system that compiles all code in a project into a single assembly (similar to VS 2003 -- but without many of the limitations that VS 2003 web projects had with regard to FrontPage Server Extensions, IIS dependencies, and other issues).  To learn more about VS 2005 Web Application Projects, please review the tutorials I&#39;ve published on my &lt;a href=&quot;http://webproject.scottgu.com/&quot; target=&quot;_blank&quot;&gt;http://webproject.scottgu.com&lt;/a&gt; web-site.  Note that VS 2005 Web Application Project support will be included in VS 2005 SP1 (so no additional download will be required going forward).&lt;/span&gt;&lt;/p&gt;&lt;span style=&quot;;font-family:arial;font-size:85%;&quot;  &gt; &lt;/span&gt;&lt;p&gt;&lt;span style=&quot;;font-family:arial;font-size:85%;&quot;  &gt;Both the VS 2005 Web Site Project option and the VS 2005 Web Application Project option will continue to be &lt;u&gt;fully supported&lt;/u&gt; going forward with future Visual Studio releases.  What we&#39;ve found is that some people love one option, while disliking the other, and vice-versa.  From a feature perspective there is no &quot;one best option&quot; to use - it really depends on your personal preferences and team dynamics as to which will work best for you.  For example: a lot of enterprise developers love the VS 2005 Web Application option because it provides a lot more build control and team integration support, while a lot of web developers love the VS 2005 Web Site model because of its &quot;just hit save&quot; dynamic model and flexibility.&lt;/span&gt;&lt;/p&gt;&lt;span style=&quot;;font-family:arial;font-size:85%;&quot;  &gt; &lt;/span&gt;&lt;p&gt;&lt;span style=&quot;;font-family:arial;font-size:85%;&quot;  &gt;Two articles you might find useful to decide which works best for you is &lt;a href=&quot;http://msdn.microsoft.com/vstudio/default.aspx?pull=/library/en-us/dnvs05/html/WAP.asp&quot; target=&quot;_blank&quot;&gt;this MSDN whitepaper&lt;/a&gt; that includes some comparisons between the two models, and Rick Strahl&#39;s &lt;a href=&quot;http://west-wind.com/weblog/posts/5601.aspx&quot; target=&quot;_blank&quot;&gt;Web Application Projects and Web Deployment Projects are Here&lt;/a&gt; article that provides a good discussion of the pros/cons of the different options.&lt;/span&gt;&lt;/p&gt;&lt;span style=&quot;;font-family:arial;font-size:85%;&quot;  &gt; &lt;/span&gt;&lt;p&gt;&lt;span style=&quot;;font-family:arial;font-size:85%;&quot;  &gt;To migrate from the VS 2005 Web Site Project model to the VS 2005 Web Application Project model, please follow this &lt;a href=&quot;http://webproject.scottgu.com/CSharp/Migration2/Migration2.aspx&quot; target=&quot;_blank&quot;&gt;C#&lt;/a&gt; or &lt;a href=&quot;http://webproject.scottgu.com/VisualBasic/Migration2/Migration2.aspx&quot; target=&quot;_blank&quot;&gt;VB&lt;/a&gt; tutorial that walks-through the steps for how to-do so.&lt;/span&gt;&lt;/p&gt;&lt;span style=&quot;;font-family:arial;font-size:85%;&quot;  &gt; &lt;/span&gt;&lt;p&gt;&lt;span style=&quot;;font-family:arial;font-size:85%;&quot;  &gt;&lt;strong&gt;So Which Project Option Builds Faster?&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;span style=&quot;;font-family:arial;font-size:85%;&quot;  &gt; &lt;/span&gt;&lt;p&gt;&lt;span style=&quot;;font-family:arial;font-size:85%;&quot;  &gt;When doing full builds of projects, the VS 2005 Web Application Project option will compile projects much faster that the VS 2005 Web Site Project option.  By &quot;full build&quot; I mean cases where every class and page in a project is being compiled and re-built - either because you selected a &quot;Rebuild&quot; option within your &quot;build&quot; menu, or because you modified code within a dependent class library project or in the /app_code directory and then hit &quot;build&quot; or &quot;ctrl-shift-b&quot; to compile the solution.  &lt;/span&gt;&lt;/p&gt;&lt;span style=&quot;;font-family:arial;font-size:85%;&quot;  &gt; &lt;/span&gt;&lt;p&gt;&lt;span style=&quot;;font-family:arial;font-size:85%;&quot;  &gt;There are a few reasons why the VS 2005 Web Application Project ends up being significantly faster than Web Site Projects in these &quot;full rebuild&quot; scenarios.  The main reason is that (like VS 2003), the VS 2005 Web Application Project option only compiles your page&#39;s code-behind code and other classes within your project.  It &lt;em&gt;does not&lt;/em&gt; analyze or compile the content/controls/in-line code within your .aspx pages -- which means it does not need to parse those files.  On the downside this means that during compilation it will not check for errors in those files (unlike the VS 2005 Web Site Project option which will identify any errors there).  On the positive side it makes compilations much faster.&lt;/span&gt;&lt;/p&gt;&lt;span style=&quot;;font-family:arial;font-size:85%;&quot;  &gt; &lt;/span&gt;&lt;p&gt;&lt;span style=&quot;;font-family:arial;font-size:85%;&quot;  &gt;So does this mean that you should always use the VS 2005 Web Application Project option to get the fastest build times with large projects?  No -- not necessarily.  One nice feature that you can enable with the VS 2005 Web Site Project option is support for doing &quot;on demand compilation&quot;.  This avoids you having to always re-build an entire project when dependent changes are made -- instead you can just re-build those pages you are working on and do it on-demand.  This will lead to significant build performance improvements for your solution, and can give you a very nice workflow when working on very large projects.  I would definitely recommend using this option if you want to improve your build performance, while retaining the flexibility of the web-site model.&lt;/span&gt;&lt;/p&gt;&lt;span style=&quot;;font-family:arial;font-size:85%;&quot;  &gt; &lt;/span&gt;&lt;p&gt;&lt;span style=&quot;;font-family:arial;font-size:85%;&quot;  &gt;The below sections provide specific tutorials for both the VS 2005 Web Site Project Model and the VS 2005 Web Application Project Model on optimization techniques -- including the &quot;on demand compilation&quot; build option I described above.&lt;/span&gt;&lt;/p&gt;&lt;span style=&quot;;font-family:arial;font-size:85%;&quot;  &gt; &lt;/span&gt;&lt;p&gt;&lt;span style=&quot;;font-family:arial;font-size:85%;&quot;  &gt;&lt;strong&gt;Specific Tips/Tricks for Optimizing VS 2005 Web Site Project Build Times&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;span style=&quot;;font-family:arial;font-size:85%;&quot;  &gt; &lt;/span&gt;&lt;p&gt;&lt;span style=&quot;;font-family:arial;font-size:85%;&quot;  &gt;When using the VS 2005 Web Site Project model, you can significantly improve build performance times by following these steps:&lt;/span&gt;&lt;/p&gt;&lt;span style=&quot;;font-family:arial;font-size:85%;&quot;  &gt; &lt;/span&gt;&lt;p&gt;&lt;span style=&quot;;font-family:arial;font-size:85%;&quot;  &gt;1) Verify that you are not suffering from an issue I call &quot;Dueling Assembly References&quot;.  I describe how to both detect and fix this condition in &lt;a href=&quot;http://weblogs.asp.net/scottgu/archive/2006/07/30/Common-Gotcha_3A00_-Slow-VS-2005-Web-Site-Build-Performance-Because-of-_1C20_Dueling-Assembly-References_1D20_.aspx&quot; target=&quot;_blank&quot;&gt;this blog post&lt;/a&gt;.  If you are ever doing a build and see the compilation appear to pause in the &quot;Validating Web Site&quot; phase of compilation (meaning no output occurs in the output window for more than a few seconds), then it is likely that you are running into this problem.  Use the techniques &lt;a href=&quot;http://weblogs.asp.net/scottgu/archive/2006/07/30/Common-Gotcha_3A00_-Slow-VS-2005-Web-Site-Build-Performance-Because-of-_1C20_Dueling-Assembly-References_1D20_.aspx&quot; target=&quot;_blank&quot;&gt;outlined in this blog post&lt;/a&gt; to fix it.&lt;/span&gt;&lt;/p&gt;&lt;span style=&quot;;font-family:arial;font-size:85%;&quot;  &gt; &lt;/span&gt;&lt;p&gt;&lt;span style=&quot;;font-family:arial;font-size:85%;&quot;  &gt;2) Keep the number of files in your /app_code directory small.  If you end up having a lot of class files within this directory, I&#39;d recommend you instead add a separate class library project to your VS solution and move these classes within that instead since class library projects compile faster than compiling classes in the /app_code directory.  This isn&#39;t usually an issue if you just have a small number of files in /app_code, but if you have lots of directories or dozens of files you will be able to get speed improvements by moving these files into a separate class library project and then reference that project from your web-site instead.  One other thing to be aware of is that whenever you switch from source to design-view within the VS HTML designer, the designer causes the /app_code directory to be compiled before the designer surface loads.  The reason for this is so that you can host controls defined within /app_code in the designer.  If you don&#39;t have an /app_code directory, or only have a few files defined within it, the page designer will be able to load much quicker (since it doesn&#39;t need to perform a big compilation first).&lt;/span&gt;&lt;/p&gt;&lt;span style=&quot;;font-family:arial;font-size:85%;&quot;  &gt; &lt;/span&gt;&lt;p&gt;&lt;span style=&quot;;font-family:arial;font-size:85%;&quot;  &gt;3) Enable the on-demand compilation option for your web-site projects.  To enable this, right-click on your web-site project and pull up the project properties page.  Click the &quot;Build&quot; tab on the left to pull up its build settings.  Within the &quot;Build&quot; tab settings page change the F5 Start Action from &quot;Build Web Site&quot; to either the &quot;Build Page&quot; or &quot;No Build&quot; option.  Then make sure to uncheck the &quot;Build Web site as part of solution&quot; checkbox:&lt;/span&gt;&lt;/p&gt;&lt;span style=&quot;;font-family:arial;font-size:85%;&quot;  &gt; &lt;/span&gt;&lt;p&gt;&lt;span style=&quot;;font-family:arial;font-size:85%;&quot;  &gt;&lt;img src=&quot;http://www.scottgu.com/blogposts/buildperf/step1.jpg&quot; /&gt; &lt;/span&gt;&lt;/p&gt;&lt;span style=&quot;;font-family:arial;font-size:85%;&quot;  &gt; &lt;/span&gt;&lt;p&gt;&lt;span style=&quot;;font-family:arial;font-size:85%;&quot;  &gt;When you click ok to accept these changes you will be running in an on-demand compilation mode.  What this means (when you select the &quot;Build Page&quot; option in the dialog above) is that when you edit a page and then hit F5 (run with debugging) or Ctrl-F5 (run without debugging) the solution will compile all of the class library projects like before, then compile the /app_code directory and Global.asax file, and then instead of re-verifying all pages within the web-site it will only verify the current page you are working on, and any user controls that the page references.  With large (and even medium) projects with lots of pages, this can obviously lead to major performance wins.  Note that ASP.NET will automatically re-compile any other page or control you access at runtime -- so you will always have an up-to-date and current running application (you don&#39;t need to worry about old code running).  You can optionally also use the &quot;No Build&quot; option to by-pass page-level validation in the IDE, which obviously speeds up the entire process much further (I&#39;d recommend giving both options a try to see which you prefer).  &lt;/span&gt;&lt;/p&gt;&lt;span style=&quot;;font-family:arial;font-size:85%;&quot;  &gt; &lt;/span&gt;&lt;p&gt;&lt;span style=&quot;;font-family:arial;font-size:85%;&quot;  &gt;By deselecting the &quot;Build Web site as part of solution&quot; checkbox, you will find that the Ctrl-Shift-B keystroke (which builds the solution) will continue compiling all class library projects, but will not re-build all pages within your web-site project.  You will still get full intellisense support in your pages in this scenario - so you won&#39;t lose any design-time support.  You will also continue to get warning/error squiggles in code/class when they are open.  If you want a way to force a re-build to occur on pages not open, or across all pages within the web-site, you can use the &quot;Build Page&quot; or &quot;Build Web Site&quot; menu options within the &quot;Build&quot; menu of Visual Studio:&lt;/span&gt;&lt;/p&gt;&lt;span style=&quot;;font-family:arial;font-size:85%;&quot;  &gt; &lt;/span&gt;&lt;p&gt;&lt;span style=&quot;;font-family:arial;font-size:85%;&quot;  &gt;&lt;img src=&quot;http://www.scottgu.com/blogposts/buildperf/step2.jpg&quot; /&gt; &lt;/span&gt;&lt;/p&gt;&lt;span style=&quot;;font-family:arial;font-size:85%;&quot;  &gt; &lt;/span&gt;&lt;p&gt;&lt;span style=&quot;;font-family:arial;font-size:85%;&quot;  &gt;This gives you control as to which pages on your site you want to verify (and when) - and can significantly improve build performance.  One trick I recommend doing is adding a new shortcut keystroke to your environment to allow you to quickly short-cut the &quot;Build Page&quot; menu option to avoid you having to ever use a mouse/menu for this.  You can do this by selecting the Tools-&gt;Customize menu item, and then click the &quot;Keyboards&quot; button on the bottom-left of the customize dialog.  This will bring up a dialog box that allows you to select the VS Build.BuildPage command and associate it within any keystroke you want:&lt;/span&gt;&lt;/p&gt;&lt;span style=&quot;;font-family:arial;font-size:85%;&quot;  &gt; &lt;/span&gt;&lt;p&gt;&lt;span style=&quot;;font-family:arial;font-size:85%;&quot;  &gt;&lt;img src=&quot;http://www.scottgu.com/blogposts/buildperf/step3.jpg&quot; /&gt; &lt;/span&gt;&lt;/p&gt;&lt;span style=&quot;;font-family:arial;font-size:85%;&quot;  &gt; &lt;/span&gt;&lt;p&gt;&lt;span style=&quot;;font-family:arial;font-size:85%;&quot;  &gt;Once you do this, you can type &quot;Ctrl-Shift-P&quot; (or any other keystroke you set) on any page to cause VS to compile any modified class library project (effectively the same thing that Ctrl-Shift-B does), then verify all classes within the /app_code directory, and then re-build just the page or user control (and any referenced master pages or user controls it uses) that you are working on within the project.&lt;/span&gt;&lt;/p&gt;&lt;span style=&quot;;font-family:arial;font-size:85%;&quot;  &gt; &lt;/span&gt;&lt;p&gt;&lt;span style=&quot;;font-family:arial;font-size:85%;&quot;  &gt;Once the above steps are applied, you should find that your build performance and flexibility is much improved - and that you have complete control over builds happen.&lt;/span&gt;&lt;/p&gt;&lt;span style=&quot;;font-family:arial;font-size:85%;&quot;  &gt; &lt;/span&gt;&lt;p&gt;&lt;span style=&quot;;font-family:arial;font-size:85%;&quot;  &gt;&lt;strong&gt;Specific Tips/Tricks for Optimizing VS 2005 Web Application Project Build Times&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;span style=&quot;;font-family:arial;font-size:85%;&quot;  &gt; &lt;/span&gt;&lt;p&gt;&lt;span style=&quot;;font-family:arial;font-size:85%;&quot;  &gt;If you are using the VS 2005 Web Application project option, here are a few optimizations you might want to consider:&lt;/span&gt;&lt;/p&gt;&lt;span style=&quot;;font-family:arial;font-size:85%;&quot;  &gt; &lt;/span&gt;&lt;p&gt;&lt;span style=&quot;;font-family:arial;font-size:85%;&quot;  &gt;1) If you have a very large project, or are working on an application with many other developers, you might want to consider splitting it up into multiple &quot;sub-web&quot; projects.  I wouldn&#39;t necessarily recommend this for performance reasons (unless you have thousands and thousands of pages it probably doesn&#39;t make a huge difference), but it can sometimes make it easier to help manage a large project.  Please read this past &lt;a href=&quot;http://weblogs.asp.net/scottgu/archive/2006/08/16/Tip_2F00_Trick_3A00_-Creating-Sub_2D00_Web-Projects-using-the-VS-2005-Web-Application-Project-Option.aspx&quot; target=&quot;_blank&quot;&gt;blog-post of mine on creating sub-web projects&lt;/a&gt; to learn how to use this.&lt;/span&gt;&lt;/p&gt;&lt;span style=&quot;;font-family:arial;font-size:85%;&quot;  &gt; &lt;/span&gt;&lt;p&gt;&lt;span style=&quot;;font-family:arial;font-size:85%;&quot;  &gt;2) Consider adding a VS 2005 Web Deployment project to your solution for deep verification.  I mentioned above that one downside of using the VS 2005 Web Application Project option was that it only compiled the code-behind source code of your pages, and didn&#39;t do a deeper verification of the actual .aspx markup (so it will miss cases where you have a mis-typed tag in your .aspx markup).  This provides the same level of verification support that VS 2003 provided (so you aren&#39;t loosing anything from that), but not as deep as the Web Site Project option.  One way you can still get this level of verification with VS 2005 Web Application Projects is to optionally add a &lt;a href=&quot;http://weblogs.asp.net/scottgu/archive/2005/11/06/429723.aspx&quot; target=&quot;_blank&quot;&gt;VS 2005 Web Deployment Project&lt;/a&gt; into your solution (web deployment projects work with both web-site and web-application solutions).  You can configure this to run only when building &quot;release&quot; or &quot;staging&quot; builds of your solution (to avoid taking a build hit at development time), and use it to provide a deep verification of both your content and source code prior to shipping your app.  &lt;/span&gt;&lt;/p&gt;&lt;span style=&quot;;font-family:arial;font-size:85%;&quot;  &gt; &lt;/span&gt;&lt;p&gt;&lt;span style=&quot;;font-family:arial;font-size:85%;&quot;  &gt;&lt;strong&gt;Common Tips/Tricks for Optimizing any VS 2005 Build Time&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;span style=&quot;;font-family:arial;font-size:85%;&quot;  &gt; &lt;/span&gt;&lt;p&gt;&lt;span style=&quot;;font-family:arial;font-size:85%;&quot;  &gt;Here are a few things I recommend checking anytime you have poor performance when building projects/solutions (note: this list will continue to grow as I hear new ones - so check back in the future):&lt;/span&gt;&lt;/p&gt;&lt;span style=&quot;;font-family:arial;font-size:85%;&quot;  &gt; &lt;/span&gt;&lt;p&gt;&lt;span style=&quot;;font-family:arial;font-size:85%;&quot;  &gt;1) &lt;u&gt;Watch out for Virus Checkers, Spy-Bots, and Search/Indexing Tools&lt;/u&gt;&lt;/span&gt;&lt;/p&gt;&lt;span style=&quot;;font-family:arial;font-size:85%;&quot;  &gt; &lt;/span&gt;&lt;p&gt;&lt;span style=&quot;;font-family:arial;font-size:85%;&quot;  &gt;VS hits the file-system a lot, and obviously needs to reparse any file within a project that has changed the next time it compiles.  One issue I&#39;ve seen reported several times are cases where virus scanners, spy-bot detecters, and/or desktop search indexing tools end up monitoring a directory containing a project a little too closely, and continually change the timestamps of these files (they don&#39;t alter the contents of the file - but they do change a last touched timestamp that VS also uses).  This then causes a pattern of: you make a change, rebuild, and then in the background the virus/search tool goes in and re-searches/re-checks the file and marks it as altered - which then causes VS to have to re-build it again.  Check for this if you are seeing build performance issues, and consider disabling the directories you are working on from being scanned by other programs.  I&#39;ve also seen reports of certain Spybot utilities causing extreme slowness with VS debugging - so you might want to verify that you aren&#39;t having issues with those either.&lt;/span&gt;&lt;/p&gt;&lt;span style=&quot;;font-family:arial;font-size:85%;&quot;  &gt; &lt;/span&gt;&lt;p&gt;&lt;span style=&quot;;font-family:arial;font-size:85%;&quot;  &gt;2) &lt;u&gt;Turn off AutoToolboxPopulate in the Windows Forms Designer Options&lt;/u&gt;&lt;/span&gt;&lt;/p&gt;&lt;span style=&quot;;font-family:arial;font-size:85%;&quot;  &gt; &lt;/span&gt;&lt;p&gt;&lt;span style=&quot;;font-family:arial;font-size:85%;&quot;  &gt;There is an option in VS 2005 that will cause VS to automatically populate the toolbox with any controls you compile as part of your solution.  This is a useful feature when developing controls since it updates them when you build, but I&#39;ve seen a few reports from people who find that it can cause VS to end up taking a long time (almost like a hang) in some circumstances.  Note that this applies both to Windows Forms and Web Projects.  To disable this option, select the Tools-&gt;Options menu item, and then unselect the Windows Forms Designer/General/AutoToolboxPopulate checkbox option (for a thread on this see: &lt;a href=&quot;http://forums.asp.net/1108115/ShowPost.aspx&quot; target=&quot;_blank&quot;&gt;http://forums.asp.net/1108115/ShowPost.aspx&lt;/a&gt;).&lt;/span&gt;&lt;/p&gt;&lt;span style=&quot;;font-family:arial;font-size:85%;&quot;  &gt; &lt;/span&gt;&lt;p&gt;&lt;span style=&quot;;font-family:arial;font-size:85%;&quot;  &gt;3) &lt;u&gt;Examine which 3rd party packages are running in Visual Studio&lt;/u&gt;&lt;/span&gt;&lt;/p&gt;&lt;span style=&quot;;font-family:arial;font-size:85%;&quot;  &gt; &lt;/span&gt;&lt;p&gt;&lt;span style=&quot;;font-family:arial;font-size:85%;&quot;  &gt;There are a lot of great 3rd party VS packages that you can plug into Visual Studio.  These deliver big productivity wins, and offer tons of features.  Occasionally I&#39;ve seen issues where performance or stability is being affected by them though.  This is often true in cases where an older version (or beta) of one of these packages is being used (always keep an eye out for when a manufacturer updates them with bug-fixes).  If you are seeing issues with performance or stability, you might want to look at trying a VS configuration where you uninstall any additional packages to see if this makes a difference.  If so, you can work with the 3rd party manufacturer to identify the issue.  &lt;/span&gt;&lt;/p&gt;&lt;span style=&quot;;font-family:arial;font-size:85%;&quot;  &gt; &lt;/span&gt;&lt;p&gt;&lt;span style=&quot;;font-family:arial;font-size:85%;&quot;  &gt;&lt;strong&gt;Visual Basic Build Performance HotFix&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;span style=&quot;;font-family:arial;font-size:85%;&quot;  &gt; &lt;/span&gt;&lt;p&gt;&lt;span style=&quot;;font-family:arial;font-size:85%;&quot;  &gt;The Visual Basic team has released several hotfixes for compilation performance issues with large VB projects.  You can learn &lt;a href=&quot;http://blogs.msdn.com/webdevtools/archive/2006/07/24/677180.aspx&quot; target=&quot;_blank&quot;&gt;how to obtain these hotfixes immediately from this blog post&lt;/a&gt;.  The VB team also has a direct email address -- &lt;a href=&quot;mailto:vbperf@microsoft.com&quot;&gt;vbperf@microsoft.com&lt;/a&gt; -- that you can use to contact them directly if you are running into performance issues.&lt;/span&gt;&lt;/p&gt;&lt;span style=&quot;;font-family:arial;font-size:85%;&quot;  &gt; &lt;/span&gt;&lt;p&gt;&lt;span style=&quot;;font-family:arial;font-size:85%;&quot;  &gt; &lt;/span&gt;&lt;/p&gt;&lt;span style=&quot;;font-family:arial;font-size:85%;&quot;  &gt; &lt;/span&gt;&lt;p&gt;&lt;span style=&quot;;font-family:arial;font-size:85%;&quot;  &gt;Hope this helps,&lt;/span&gt;&lt;/p&gt;&lt;span style=&quot;;font-family:arial;font-size:85%;&quot;  &gt; &lt;/span&gt;&lt;p&gt;&lt;span style=&quot;;font-family:arial;font-size:85%;&quot;  &gt;Scott&lt;br /&gt;original link: http://weblogs.asp.net/scottgu/archive/2006/09/22/&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;octopus east java baker&lt;/div&gt;</description><link>http://scriptster.blogspot.com/2007/09/tiptrick-optimizing-aspnet-20-web.html</link><author>noreply@blogger.com (Octopus)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-2977499297091575918.post-6770772645169439790</guid><pubDate>Tue, 18 Sep 2007 01:54:00 +0000</pubDate><atom:updated>2007-09-17T18:55:22.573-07:00</atom:updated><title>Dependency injection in PHP5</title><description>Several months ago I started using &lt;a href=&quot;http://www.springframework.org&quot;&gt;Spring Framework &lt;/a&gt;. That is how I faced the &lt;a href=&quot;http://martinfowler.com/articles/injection.html&quot;&gt;dependency injection &lt;/a&gt;. As my programming skills mostly originated from web development with PHP, I found out that I&#39;ve missed a great technique, which is as usually common in Java land, but rare in PHP. I ended up with a research of dependency injection libraries for PHP. There was a port of &lt;a href=&quot;http://www.picocontainer.org/&quot;&gt;Pico container &lt;/a&gt; by Pawel Kozlowski, who gave a &lt;a href=&quot;http://www.phpconference.co.uk/2006/talks/pico/dependency_injection_-_pawel_kozlowski.html&quot;&gt;talk &lt;/a&gt; on it recently, and that was almost it (some bright minds from #php.thinktank had their own solutions for that). &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;However, all these solutions made you to define your dependencies within the code of your application, and were quite minimalistic. That made my mind - I started working on &lt;a href=&quot;http://garden.clawphp.org&quot;&gt;Garden &lt;/a&gt; - the dependency injection container for PHP5, which would use XML definitions with syntax as similar as possible to the Spring. Today Garden is packed up and ready for use. Here is a sample application context that injects a collar on a dog: &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&amp;lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&amp;gt; &lt;br&gt;&lt;br /&gt;&amp;lt;!DOCTYPE beans PUBLIC &quot;-//GARDEN//DTD BEAN//EN&quot; &quot;garden-beans.dtd&quot;&amp;gt; &lt;br&gt;&lt;br /&gt;&amp;lt;beans default-lazy-init=&quot;true&quot;&amp;gt; &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;lt;bean id=&quot;dog&quot; class=&quot;Dog&quot; file=&quot;ext/Dog.php&quot;&amp;gt; &lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;property name=&quot;collar&quot;&amp;gt; &lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;ref local=&quot;dogCollar&quot;/&amp;gt; &lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/property&amp;gt; &lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;lt;/bean&amp;gt; &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;lt;bean id=&quot;dogCollar&quot; class=&quot;Collar&quot; file=&quot;ext/Dog/Collar.php&quot;&amp;gt; &lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;property name=&quot;spiked&quot; value=&quot;true&quot;/&amp;gt; &lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;lt;/bean&amp;gt; &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;&amp;lt;/beans&amp;gt; &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;The contents of Dog and Collar classes: &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;class Dog &lt;br&gt;&lt;br /&gt;{ &lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; private $collar; &lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public function setCollar($collar) &lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $this-&amp;gt;collar = $collar; &lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public function getCollar() &lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return $this-&amp;gt;collar; &lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br&gt;&lt;br /&gt;} &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;class Collar &lt;br&gt;&lt;br /&gt;{ &lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; private $spiked; &lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public function setSpiked($spiked) &lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $this-&amp;gt;spiked = $spiked; &lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public function getSpiked() &lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return $this-&amp;gt;spiked; &lt;br&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br&gt;&lt;br /&gt;} &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;And finally, a piece of code to access the beans: &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;require_once &#39;Garden.php&#39;; &lt;br&gt;&lt;br /&gt;Garden::initApplicationContext(&#39;example.xml&#39;); &lt;br&gt;&lt;br /&gt;$ctx = Garden::getApplicationContext(); &lt;br&gt;&lt;br /&gt;$dog = $ctx-&amp;gt;getBean(&#39;dog&#39;); &lt;br&gt;&lt;br /&gt;$collar1 = $dog-&amp;gt;getCollar(); &lt;br&gt;&lt;br /&gt;$collar2 = $ctx-&amp;gt;getBean(&#39;dogCollar&#39;); &lt;br&gt;&lt;br /&gt;var_dump($dog, $collar1, $collar1 === $collar2); &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;The output of dump: &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;object(Dog)#1 (1) { &lt;br&gt;&lt;br /&gt;[&quot;collar:private&quot;]=&amp;gt; &lt;br&gt;&lt;br /&gt;object(Collar)#2 (1) { &lt;br&gt;&lt;br /&gt;[&quot;spiked:private&quot;]=&amp;gt; &lt;br&gt;&lt;br /&gt;bool(true) &lt;br&gt;&lt;br /&gt;} &lt;br&gt;&lt;br /&gt;} &lt;br&gt;&lt;br /&gt;object(Collar)#2 (1) { &lt;br&gt;&lt;br /&gt;[&quot;spiked:private&quot;]=&amp;gt; &lt;br&gt;&lt;br /&gt;bool(true) &lt;br&gt;&lt;br /&gt;} &lt;br&gt;&lt;br /&gt;bool(true) &lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;This example reveals only a basic setter injection, however the possibilities allow to use constructor argument injection, nested bean definitions, combined XML definition resources, aliasing, and literally almost all functionality found &lt;a href=&quot;http://static.springframework.org/spring/docs/2.0.x/reference/beans.html&quot;&gt;here &lt;/a&gt;. I hope this will be helpful for those of you who work on large scale, and trust that PHP applications can be scalable, easily maintainable and designed well. Make your applications blossom!&lt;div class=&quot;blogger-post-footer&quot;&gt;octopus east java baker&lt;/div&gt;</description><link>http://scriptster.blogspot.com/2007/09/dependency-injection-in-php5.html</link><author>noreply@blogger.com (Octopus)</author><thr:total>0</thr:total></item></channel></rss>