by Nik Kalyani
Wednesday, January 02, 2008 11:24:27 PM (Pacific Standard Time, UTC-08:00)
DotNetKicks is a Digg-like site focused on .NET development. Thanks for Jon Galloway's useful tip, I figured out how to add a dynamic Kick image to my posts. He has Javascript code, but I just hard-coded the following into the DasBlog itemTemplate.blogTemplate file for the theme in use: <a href="http://www.dotnetkicks.com/kick/?url=<%PermalinkUrl%>"><img align="absmiddle" src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=<%PermalinkUrl%>"></a>
I have not figured out how to dynamically make the link appear only when a specific category such as .NET is selected, but this is good for now. Of course, this is of no use if I don't post anything worth kicking.
by Nik Kalyani
Wednesday, February 01, 2006 7:53:24 PM (Pacific Standard Time, UTC-08:00)
The IE7 toolbar has an RSS icon that is ordinarily grayed-out, but lights up when visiting certain web pages.
Clicking the icon displays a list of feeds available on the page. When
you select a feed you see a formatted version of the feed along with
options to subscribe to the feed and change the sort order of items.
Once you subscribe to the feed, it gets added to the “Favorites Center”
which you can open to organize your feeds or view them.
If you are a web developer and have made RSS feeds available on your
web pages, you can make discovery and subscription of these feeds
easier for IE7 users by adding a few elements to your page
that announce the presence of the feeds. Adding
a <LINK> tag to the page Head with the correct
attributes will do the trick. For example, my blog has the following:
<link rel="alternate" type="application/rss+xml" title="My RSS Feed" ref="http://blogs.speerio.net/peerio/SyndicationService.asmx/GetRss" />
As you can see, this is quite simple; you just have to add the
attributes “rel,” type,” “title,” and “ref”. This is a simple
addition that will instantly make your RSS feeds easier to
consume.
by Nik Kalyani
Monday, January 23, 2006 10:48:53 AM (Pacific Standard Time, UTC-08:00)
There are many situations when you may want to dynamically add a stylesheet to a page. One use case is when a control is being dynamically loaded and it comes with its own stylesheet. If you don’t know that the style is needed in advance or are dealing with an environment where you have a stylesheet for a control but don’t have control of the page (as it is in DotNetNuke), there are two common methods in use:
1) Add a <LINK> tag: This works but leaves the parent page non-XHTML compliant since <LINK> is only valid in the <HEAD> section.
2) Add a <STYLE> element and add the styles to the page. This works but gives you a bloated page and does not take advantage of stylesheet caching.
The solution is to dynamically add a stylesheet to the page. Here’s how.
(Internet Explorer makes this easy to do with Javascript using document.createStyleSheet. For other browsers, you have to get a handle to the <HEAD> element and then insert the stylesheet.)
bool isIE = (HttpContext.Current.Request.Browser.Browser == "IE" ? true : false); string stylesheetUrl = “/test/default.css”; StringBuilder styleScript = new StringBuilder(); styleScript.Append("<script language=\"javascript\">"); if (isIE) styleScript.Append("document.createStyleSheet(\"" + styleSheetUrl + “\");"); else styleScript.Append("var newStyleSheet=document.createElement(\"link\"); newStyleSheet.rel=\"stylesheet\"; newStyleSheet.href=\"" + styleSheetUrl + “\”; document.getElementsByTagName(\"head\")[0].appendChild(newStyleSheet);"); styleScript.Append("</script>"); Page.RegisterClientScriptBlock(“MyStylesheet”, styleScript.ToString());
For IE, the script adds the stylesheet directly. For other browsers, it creates a new <LINK> element on the page and then adds it at the end of list of <HEAD> elements.
by Nik Kalyani
Sunday, January 15, 2006 9:08:03 PM (Pacific Standard Time, UTC-08:00)
Discovered something quite by accident today. If you use an embedded file in a VS.Net project and have the filename in the format [basename].[locale].[extension] (example: MyInfo.en-US.xml), VS.Net automatically presumes that this is a culture-specific resource, puts it in a separate assembly and drops it into a subfolder of the main “bin” folder. The subfolder has the same name as the locale.
I am not sure if there’s an easy way around it, but for now, I simply removed the locale from the filename and it works as expected.
by Nik Kalyani
Tuesday, November 01, 2005 7:11:26 AM (Pacific Standard Time, UTC-08:00)
Like many other ASP.Net developers, I couldn’t wait to get my hands on the final VS.Net 2005, SQL 2005 and ASP.Net 2 bits off the MSDN site. This past weekend, after what seemed like an eternity, I managed to get the 4GB+ DVD images downloaded. Knowing that the installation programs would want a clean slate, I first uninstalled everything, including .Net 2 beta.
I then proceeded to install the release version of .Net 2 (small download) just to test some apps that I have sitting around. Everything worked as expected. Great!
When my downloads were finally completed, I proceeded to install VS.Net 2005. The install program complained right away that the old bits need to be uninstalled. And it was right…I had missed the Document Explorer. Click – click – click…it’s uninstalled. Nope…that didn’t do it. Still complaining about something.
I couldn’t figure it out and finally decided to take a shot in the dark and uninstall .Net 2 Release version. That did it!
Now, I may be exaggerating, but that is just INSANE. To require uninstallation of the .Net framework (release version) to get VS.Net 2005 installed is just plain stupid.
Microsoft needs to fix this, and while they are at it, can we dispense with installation programs altogether. With all the talented engineers on Microsoft’s payroll, isn’t there a small team that can replicate what has been available on the Mac for two decades now…just copy (or XCopy in Winspeak) files and you are done. Microsoft should stop trying to impress us with spiffy U.I.’s and focus on getting the basics right first.
I want to be able to copy a folder containing an app’s files from a CD or DVD onto my computer and have the application work without sitting through five minutes of progress bar hell. (And don’t even get me started on app restarts and system reboots.)
So Scoble and whoever else at Microsoft is listening…for the love of God…fix this!!! Free us from installation and progress bar hell.
Maybe we should add up all the time people worldwide have spent staring at progress bars for the last decade and send Microsoft a bill. Let’s see, if 50 million people each spent two hours waiting on app installations in the past decade and the average hourly rate is $25/hour, that’s a cool $2.5 billion. Spend even 1/1000th of that and the problem can be solved.
If Microsoft’s engineers were forced to evaluate features in terms of productivity dollars, Windows would be a very different beast. Too bad for us that user productivity is only a marketing mantra at Microsoft.
by Nik Kalyani
Tuesday, August 16, 2005 4:53:06 PM (Pacific Standard Time, UTC-08:00)
ASP.Net supports dynamic code generation and compilation. Sometimes, you just need a quick and dirty solution. This is one such solution. It writes out a control script, loads it and then deletes the file.
string dynamicControlUrl = "~/" + System.Guid.NewGuid().ToString() + ".ascx"; string dynamicControlPath = Server.MapPath(dynamicControlUrl); TextWriter tw = new StreamWriter(dynamicControlPath); tw.WriteLine("<%@ Control language=\"c#\" %>"); tw.WriteLine("<script runat=\"server\">"); tw.WriteLine(" protected void Page_Load(object s, EventArgs e)"); tw.WriteLine(" {"); tw.WriteLine(" Response.Write(\"Hello World!\");"); tw.WriteLine(" }"); tw.WriteLine("</script>"); tw.Flush(); tw.Close(); Control dynamicControl = Page.LoadControl(dynamicControlUrl); Page.Controls.AddAt(0, dynamicControl); dynamicControl = null; File.Delete(dynamicControlPath);
by Nik Kalyani
Tuesday, July 05, 2005 6:42:52 PM (Pacific Standard Time, UTC-08:00)
Now that I have made significant progress in my WebDAV server API implementation, I can post some details.
My goal is to create an API that faithfully implements RFC2518. This RFC outlines the Http/1.1 Extensions that constitute the WebDAV protocol. There are two levels: Level 1, general WebDAV support, and Level 2, locking support. I plan on supporting both levels, but for the 0.xx release will release with Level 1 support only.
I have designed the API so any developer who knows how to code with a .Net language can use the API. Zero knowledge of WebDAV is required. To use the API, a developer would need to:
1) Reference the API assembly from her/his class project.
2) Provide an implementation of abstract classes WebDAVCollection and WebDAVItem. Basically, you have to map your data store collections and items so that when the API requests a collection or an item, it gets one.
3) Provide an implementation of abstract WebDAVAuthentication class.
To put it in use, you have to:
1) Configure IIS to support file extension .davx and have it respond to all verbs (the extension is irrelevant; if you want, you can have it be .foobar, as long as it responds to all verbs).
2) Add a line similar to the following in your web.config: <add verb="*" path="MyFiles.davx" type="MyCompany.WebDAV, MyCompany.WebDAV" />
3) Create a file with the name used in #2 (i.e. MyFiles.davx). This file can be empty.
With this in place, Windows or Mac clients can natively map a drive letter using http://yourserver/MyFiles.davx as the path. Alternately, they can directly open a resource as a file from applications such as Word, Excel, HomeSite etc.
I have designed the API so each unique data store type on the server, would have an end-point ({something}.davx) and a line in the web.config.
For example, a handler such as DotNetNukeHTML.davx could be placed in the root of a DotNetNuke portal. A user on a Windows or Mac platform could then map a drive letter using http://yourserver/DotNetNukeHTML.davx/NNN where NNN is the DotNetNuke Portal ID. The user would then see a folder structure where each folder corresponds to a DotNetNuke tab. Within each folder are files corresponding to DotNetNuke module instances. Initially I plan on supporting only the HTML and NukeHTML modules so you would only see files for each instance of these modules. You could then open any of the files using Word, HomeSite or any other HTML Editor and edit the file and save it back. Of course, you can also create a new file which will result in a new module instance being added to the page.
This will basically eliminate the need to use a browser-based editor to create/modify portal content. Just use any rich Windows or Mac editors at your disposal.
This is one example. Using the API, you could also allow full file management on the web server, view a mailbox as a collection of EML files, open up a database table in Excel, there is really no limit to the possibilities. As long as you can figure out a way to present your data (any format) as a data stream that represents the file content expected by a WebDAV-enabled desktop app, you can enable native WebDAV access to your app.
Here's an illustration that gives an overview of how things will work:

by Nik Kalyani
Sunday, June 12, 2005 8:54:59 PM (Pacific Standard Time, UTC-08:00)
If you have multiple controls in your ASP.Net, especially third-party ones, which in turn have a dependency on another third-party component, you are in for a world of pain if different controls use different versions of the same third-party component. Since your app has only one "bin" folder where all the assemblies reside, putting one version of the third-party component will break controls that rely on the other version. Luckily, the .Net developers devised some good solutions. Although I would not call this an elegant solution to DLL hell, at least its possible to have a solution that works.
Here are some sample web application scenarios and solutions involving assembly version conflicts, different assembly versions and location of assemblies. This is a small portion of a much larger .Net design involving the GAC etc., but I am not going to delve into that.
1) Placing assemblies outside the bin folder.
Sometimes you have an app with many assemblies and you want to keep them more organized. .Net allows this by providing a way to specify the folders where it should search. Modify your web.config as below:
<configuration> <runtime> <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> <probing privatePath="bin;somefolder\bin" /> </assemblyBinding> </runtime> </configuration
You can specify as many folders as necessary in a semi-colon separated list which fusion will use to locate an assembly.
2) Having multiple versions of the same assembly in the same app space.
In this example, two versions of the ThirdParty assembly are placed in numbered sub-folders of bin. Both can co-exist and will work correctly.
<configuration> <runtime> <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> <dependentAssembly> <assemblyIdentity name="ThirdParty" publicKeyToken="16dcc87a28w7w7b1" /> <codeBase version="1.4.0.0" href="bin\14\ThirdParty.dll" /> <codeBase version="1.2.0.0" href="bin\12\ThirdParty.dll" /> </dependentAssembly> </assemblyBinding> </runtime> </configuration>
3) Redirecting an assembly from an older to a newer version.
<configuration> <runtime> <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> <dependentAssembly> <assemblyIdentity name="myAssembly" publicKeyToken="32ab4ba45e0a69a1" culture="neutral" /> <bindingRedirect oldVersion="1.0.0.0" newVersion="2.0.0.0"/> </dependentAssembly> </assemblyBinding> </runtime> </configuration>
You can only use #2 or #3 with strong named assemblies.
by Nik Kalyani
Sunday, May 15, 2005 3:31:24 PM (Pacific Standard Time, UTC-08:00)
I am working on implementing a WebDAV server for ASP.Net. Yes, I know this capability is built-into IIS6, but unfortunately, it requires that you enable WebDAV on the server, creating a big security hole. Additionally, the built-in implementation is unable to authenticate against a custom membership provider. In any event, my solution is a drop-in component that instantly enables WebDAV capabilities for any ASP.Net app.
One of the challenges when developing any app that relies on headers for passing commands back and forth (as WebDAV does), is that debugging is quite challenging. I explored several tools to sniff HTTP traffic, including a few that were implemented as ISAPI filters. I found all to be cumbersome and requiring sever-side installation. There are many IE add-ons that do this also, but since I am working with WebDAV, there is no browser in the equation. It's purely traffic between Windows and a WebDAV server.
I had resorted to logging to a file from within my app, until I chanced upon HTTPLook. Wow! This app is awesome. It not only does exactly what I want, but it also has a simple and elegant U.I. (important to me) and has excellent features such as filtered capture etc.
My WebDAV development has become several orders of magnitude easier, thanks to this tool. And as a bonus, the app comes with a CHM help file containing the entire HTTP spec. Too cool.
by Nik Kalyani
Saturday, May 07, 2005 9:26:05 AM (Pacific Standard Time, UTC-08:00)
Many customers of my File Manager Pro module have asked for the ability to edit documents directly (i.e. click on an edit icon in the file listing in their browser, then edit and save the document). This is easily done for text-based files, and indeed that capability is already implemented. However, for files that require a client-side application, this is not at all simple.
Let's use Microsoft Word as an example. If you click on a Word doc link in your browser, by way of the mime type (or extension as a fall back), the browser is able to determine which application should be launched. It downloads the file to temp storage and then passes on the location to the app after launching it. Any changes made to this document are made to the copy in temp storage and have no bearing on the original file on the web server.
To facilitate the editing of documents on web servers, both server and client must support WebDAV (Web Distributed Authoring and Versioning), a protocol that extends HTTP by defining standards for web document authoring, versioning and publishing. IIS5 and IIS6 natively support WebDAV (although the capability is not on by default.). Windows XP and Mac OS X natively support the ability to map/mount a WebDAV collection as a virtual drive. All Office apps, most Adobe apps, and many other popular applications support the ability to transparently work with documents using the WebDAV protocol. So what's the problem?
For servers on an Intranet, it is easy to enable WebDAV and create an easy to use shared document area. But then again, on an Intranet, why bother when you could have a shared drive. In a hosted scenario, WebDAV is much more difficult to implement due to the security concerns it poses. Currently, IIS does not provide a way to enable/disable WebDAV on a per web basis. So if a hosting provider were to enable WebDAV it would potentially compromise all websites on the server that were not properly secured. For this reason, WebDAV support in hosted scenarios is almost non-existent.
Also non-existent (as far as my Googling indicates), is a "server" API for a custom WebDAV implementation using ASP.Net. There are many client implementations, but if you want to be able to have WebDAV clients access a database-driven document repository, for example, you are on your own. This brings us back to File Manager Pro.
I was quite intrigued by everything WebDAV had to offer and so started doing some testing. I was pleased to find after a few hours of coding that it is possible to write a custom WebDAV server that works on ASP.Net. And so that is precisely what I am going to do. I am going to implement this as a generic API first and then use the API to add document authoring and versioning capabilities to File Manager Pro.
So far, I have tested getting a directory listing and editing a document. I have not implemented saving it, but I know it will work because my IIS logs show the request coming in with the right content.
This is quite exciting because it opens up File Manager Pro, and indeed DNN, to a whole new level of document collaboration. I am quite interested to see how this API may be used in different DNN modules in the future.
by Nik Kalyani
Saturday, April 30, 2005 6:37:28 AM (Pacific Standard Time, UTC-08:00)
Order of events in the lifecycle of an ASP.Net page:
| Phase |
What a control needs to do |
Method or event to override |
| Initialize |
Initialize settings needed during the lifetime of the incoming Web request. |
Init event (OnInit method) |
| Load view state |
At the end of this phase, the ViewState property of a control is automatically populated as described in Maintaining State in a Control. A control can override the default implementation of the LoadViewState method to customize state restoration. |
LoadViewState method |
| Process postback data |
Process incoming form data and update properties accordingly. |
LoadPostData method (if IPostBackDataHandler is implemented) |
| Load |
Perform actions common to all requests, such as setting up a database query. At this point, server controls in the tree are created and initialized, the state is restored, and form controls reflect client-side data. |
Load event
(OnLoad method) |
| Send postback change notifications |
Raise change events in response to state changes between the current and previous postbacks. |
RaisePostDataChangedEvent method (if IPostBackDataHandler is implemented) |
| Handle postback events |
Handle the client-side event that caused the postback and raise appropriate events on the server. |
RaisePostBackEvent method(if IPostBackEventHandler is implemented) |
| Prerender |
Perform any updates before the output is rendered. Any changes made to the state of the control in the prerender phase can be saved, while changes made in the rendering phase are lost. |
PreRender event (OnPreRender method) |
| Save state |
The ViewState property of a control is automatically persisted to a string object after this stage. This string object is sent to the client and back as a hidden variable. For improving efficiency, a control can override the SaveViewState method to modify the ViewState property. |
SaveViewState method |
| Render |
Generate output to be rendered to the client. |
Render method |
| Dispose |
Perform any final cleanup before the control is torn down. References to expensive resources such as database connections must be released in this phase. |
Dispose method |
| Unload |
Perform any final cleanup before the control is torn down. Control authors generally perform cleanup in Dispose and do not handle this event. |
UnLoad event (On UnLoad method) |
Note To override an EventName event, override the OnEventName method (and call base. OnEventName).
by Nik Kalyani
Saturday, April 23, 2005 5:31:40 PM (Pacific Standard Time, UTC-08:00)
If you wish to create strong named assemblies in .Net, you need to sign them. This is done using a key that you reference through the project’s AssemblyInfo.cs or AssemblyInfo.vb file. There are three attributes related to signing:
[assembly: AssemblyDelaySign(false)] Used to allow signing of the assembly with only the public key. This allows the assembly to be used during development without having to share the private key.
[assembly: AssemblyKeyFile("")] Used to specify the path to a key file.
[assembly: AssemblyKeyName("")] Used to specify the name of a key to use from the Crypto Service Provider (CSP).
If you are going to sign all your assemblies, then the AssemblyKeyName is the best option as it does not require you to remember a path to the key file each time you create a new project. It’s much easier to remember a simple name associated with the key. Here’s how you would sign an assembly using the CSP:
1) Generate a key pair: sn -k MyCompany.snk
2) Install into the CSP: sn -i MyCompany.snk MYCOMPANY
3) Use in your code: [assembly: AssemblyKeyName(“MYCOMPANY”)]
by Nik Kalyani
Thursday, April 21, 2005 9:33:00 AM (Pacific Standard Time, UTC-08:00)
Just got word from ComponentArt that I am going to be a member of their MVP Program. Quite excited about collaborating with other developers to create cool ComponentArt-based solutions for DotNetNuke.
by Nik Kalyani
Wednesday, April 20, 2005 7:31:38 PM (Pacific Standard Time, UTC-08:00)
There are many different solutions for creating tabbed content in HTML pages. For a number of my apps, I needed a simple, lightweight solution that was easy to use and to integrate with my apps. I came up with a simple solution and am sharing it here. Hopefully someone will find it useful.
The solution consists of a table containing the tabs and DIV’s representing the content for each tab. The tabs table has one cell for each tab with ID of “Tab_n” where n starts with 0 and increases by 1 for each tab. Add an onClick handler for each cell that calls tabClickHandler(n). Finally, create a DIV for each tab’s content and set its ID to be “Panel_n” where n starts with 0 and increases by 1 for each tab. Add a style attribute of “display: none” for all DIVs representing the tab content except for the first, which should be set to “display:block”.
<script language="javascript"> function tabClickHandler(tab) { i = -1; while (true) { i++; objTab = eval(document.getElementById("Tab_" + i));
if (objTab) { objTab.className = (i == tab) ? "Speerio-SelectedTab" : ((i > tab) ? "Speerio-RightTab" : "Speerio-LeftTab"); document.getElementById("Panel_" + i).style.display = (i == tab ? "block" : "none"); } else break; } } </script> <style> .Speerio-Tabs { width:100%; color: black; font-family: Verdana,Arial,Helvetica,Sans Serif} .Speerio-TabLeftSpacer {width:10%; BORDER-BOTTOM: 1px solid black} .Speerio-TabRightSpacer {width:10%; BORDER-BOTTOM: 1px solid black} .Speerio-SelectedTab { width:20%; BORDER-RIGHT: 1px solid black; BORDER-TOP: 1px solid black; BORDER-LEFT: 1px solid black} .Speerio-LeftTab {cursor: hand; width:20%; BORDER-TOP: 1px solid #cccccc; BORDER-LEFT: 1px solid #cccccc; CURSOR: hand; BORDER-BOTTOM: 1px solid black; background-color: #eeeeee} .Speerio-RightTab {cursor: hand; width:20%; BORDER-RIGHT: 1px solid #cccccc; BORDER-TOP: 1px solid #cccccc; BORDER-LEFT: medium none; CURSOR: hand; BORDER-BOTTOM: 1px solid black; background-color: #eeeeee} .Speerio-TabLabel { font-size: 8pt; font-weight: bold; color: black; font-family: Verdana,Arial,Helvetica,Sans Serif} </style> <table cellspacing="0" cellpadding="2" border="0" align="center" class="Speerio-Tabs"> <tr> <td class="Speerio-TabLeftSpacer"> </td> <td id="Tab_0" class="Speerio-SelectedTab" nowrap align="Center" valign="Middle" onClick="tabClickHandler(0)"> <span class="Speerio-TabLabel">ABC</span></td> <td id="Tab_1" class="Speerio-RightTab" nowrap align="Center" valign="Middle" onClick="tabClickHandler(1)"> <span class="Speerio-TabLabel">DEF</span></td> <td id="Tab_2" class="Speerio-RightTab" nowrap align="Center" valign="Middle" onClick="tabClickHandler(2)"> <span class="Speerio-TabLabel">GHI</span></td> <td id="Tab_3" class="Speerio-RightTab" nowrap align="Center" valign="Middle" onClick="tabClickHandler(3)"> <span class="Speerio-TabLabel">JKL</span></td>
<!-- Add as many additional cells corresponding to tabs here --> <td class="Speerio-TabRightSpacer" align="right"> </td> </tr> </table> <!-– Add a DIV for each tab’s content here -->
<div id="Panel_0" style="display:block" width="100%">Contents of the first tab</div> <div id="Panel_1" style="display:none" width="100%">Contents of the second tab</div> <div id="Panel_2" style="display:none" width="100%">Contents of the third tab</div> <div id="Panel_3" style="display:none" width="100%">Contents of the fourth tab</div>
by Nik Kalyani
Wednesday, April 20, 2005 8:46:40 AM (Pacific Standard Time, UTC-08:00)
The Secrets of Strong Naming by Mike Gunderloy -- If you've been working with .NET for any length of time, you've probably run across the concept of a strong name. No, that doesn't mean that your assemblies should have names like MyCompany.Gorilla.Biceps. The strength of a strong name lies in the protection that it offers your assemblies. The .NET Framework uses strong names to identify assemblies and to protect them from tampering. In this article, Mike Gunderloy shows you how strong names are constructed and demonstrates the mechanics of working with strong names in .NET.
by Nik Kalyani
Tuesday, March 01, 2005 12:15:14 AM (Pacific Standard Time, UTC-08:00)
.Net allows you to do some amazing things with graphics using GDI+. Its handling of image meta data leaves something to be desired though. It’s like they started to do something, but then abandoned it mid-way. In working on the Speerio File Manager Pro (for ASP.Net and DotNetNuke) product’s imaging functions, after considerable research, I decided that Omar Shahine’s PhotoLibrary was the best fit. It has some excellent functions especially in the EXIF area.
After playing with it for a while, I was disappointed to find that it, like just about every other EXIF-handler Google can find, does not preserve EXIF data on resize and rotate operations. I saw some commercial .Net components did it, so I knew could be done. But hours of searching later, all I knew for certain is that GDI+ can read EXIF data, but cannot write it to a new image. Bummer!
Not being one to give up easily, I experimenting a bit, and am pleased to have come up with a solution. Here is my JPEG resizing code which preserves EXIF data:
public static void ResizeJpeg(string filePath, int width, int height) { try
{
System.Drawing.Image imgPhoto = System.Drawing.Image.FromFile(filePath);
int sourceWidth = imgPhoto.Width;
int sourceHeight = imgPhoto.Height;
if (height == -1)
height = (int) ((float) sourceHeight * ((float) width/ (float) sourceWidth));
if (width == -1)
width = (int) ((float) sourceWidth * ((float) height/ (float) sourceHeight));
int sourceX = 0;
int sourceY = 0;
int destX = 0;
int destY = 0;
float nPercent = 0;
float nPercentW = 0;
float nPercentH = 0;
nPercentW = ((float)width/(float)sourceWidth);
nPercentH = ((float)height/(float)sourceHeight);
//if we have to pad the height pad both the top and the bottom
//with the difference between the scaled height and the desired height
if(nPercentH < nPercentW)
{
nPercent = nPercentH;
destX = (int)((width - (sourceWidth * nPercent))/2);
}
else
{
nPercent = nPercentW;
destY = (int)((height - (sourceHeight * nPercent))/2);
}
int destWidth = (int)(sourceWidth * nPercent);
int destHeight = (int)(sourceHeight * nPercent);
Bitmap bmPhoto = new Bitmap(imgPhoto, width, height);
bmPhoto.SetResolution(imgPhoto.HorizontalResolution, imgPhoto.VerticalResolution);
Graphics grPhoto = Graphics.FromImage(bmPhoto);
grPhoto.InterpolationMode = InterpolationMode.HighQualityBicubic;
grPhoto.DrawImage(imgPhoto,
new Rectangle(destX,destY,destWidth,destHeight),
new Rectangle(sourceX,sourceY,sourceWidth,sourceHeight),
GraphicsUnit.Pixel);
grPhoto.Dispose();
try
{
foreach (PropertyItem propertyItem in imgPhoto.PropertyItems)
{
try
{
bmPhoto.SetPropertyItem(propertyItem);
}
catch{}
}
}
catch{}
System.Drawing.Imaging.Encoder enc = System.Drawing.Imaging.Encoder.Quality;
System.Drawing.Imaging.EncoderParameters encParms = new EncoderParameters(1);
System.Drawing.Imaging.EncoderParameter encParm = new EncoderParameter(enc,100L);
encParms.Param[0] = encParm;
ImageCodecInfo[] codecInfo = ImageCodecInfo.GetImageEncoders();
ImageCodecInfo codecInfoJpeg = codecInfo[1];
bmPhoto.Save(filePath+".tmp",codecInfoJpeg, encParms);
bmPhoto.Dispose();
imgPhoto.Dispose();
FileInfo fileInfo = new FileInfo(filePath);
fileInfo.Delete();
fileInfo = new FileInfo(filePath+".tmp");
fileInfo.MoveTo(filePath);
}
catch{}
}
by Nik Kalyani
Wednesday, February 09, 2005 12:36:15 PM (Pacific Standard Time, UTC-08:00)
Today has been frustrating. I have been looking for a decent component that can accept a URL and generate a PDF. There are many available, but they all have server-based licensing. Does anyone know of a component that will do that, has royalty-free licensing and costs less than $1,000?
by Nik Kalyani
Monday, January 31, 2005 8:33:45 PM (Pacific Standard Time, UTC-08:00)
If you have nested ASP.Net applications, any HttpModules defined in the web.config of parent apps propogate down to the children. This can be desirable in some situations, but totally unwanted in others.
The easy way to eliminate the impact of parent HttpModules is to add a element in the child app's web.config. Sounds simple enough, until you try it.
Turns out that because of the way ASP.Net processes the web.config, even if you are clearing out HttpModules in a child app's web.config, you still need to have the requisite assemblies for the HttpModules in the child app's bin folder. Otherwise the child app will not run.
by Nik Kalyani
Friday, September 03, 2004 5:06:03 PM (Pacific Standard Time, UTC-08:00)
One of the most frequent support questions I encounter pertains to problems uploading or downloading large files using ASP.net. Assuming that these aren't super-huge files so we do not have to go into details of ASP.net's inherent inefficiencies in this area, there is usually one reason for the problem -- incorrect configuration in the web.config file.
In order to support large file uploads, ASP.net needs to be told to increase the "maxRequestLength" attribute of the "httpRuntime" element to a number larger than 4096 (Kb) which is the default.
Both uploads and downloads will fail if the "executionTimeout" attribute (also of the "httpRuntime" element) is at the default of 90 seconds. What number you set this to depends entirely on the size of the uploads/downloads the application must support and the expected bandwidth of the user. Here's the MSDN reference for httpRuntime.
|