Deploying Crystal Reports for .NET

Posted by Ikhwan on January 31, 2008

If your application uses Crystal Reports that comes with Visual Studio, you can deploy the needed DLL into the target machine by running the MSI installer located at C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\Bootstrapper\Packages\CrystalReports. For mine, it’s called CRRedist2005_x86.msi. For other version of Visual Studio, it might be named differently.

p.s: Feeling super down these couples of days :(

Prohibited IIS Extension Throws 404

Posted by Ikhwan on January 28, 2008

I just deployed my ASP.NET applications, and IIS throws me a 404. I’ve done my regular checks (not in any particular order):

  1. Check permission on folder.
  2. Allow anonymous access is enabled.
  3. Verify I correctly called the URL, and that I did create the Virtual Directory.
  4. Check if the website properly pointed to the correct IP and/or host header value.
  5. Using the correct application pool, and application pool running using proper user.
  6. Make sure IIS is installed, run aspnet_regiss -i again if needed.
  7. Allow scripts to be executed.

All seems to failed. I almost nearly went to dig into the log files when I realized and check on one more thing. In IIS 6.0, you have this thing called the Web Service Extensions.

Web Service Extension in IIS

And the fact that the “Web Service Extension” got nothing to do with SOAP web services just irks me to no end.

Flirting Editor

Posted by Ikhwan on January 28, 2008

Read reddit this morning like the usual, and there’s this link titled “My editor is flirting with me“.

That being in programming.reddit.com, I spontaneously thought that it’s about an Emacs mode or something that would print out some flowery text at the command buffer, created by some sorry coder living in a dark basement, deprecated of love.

Actually, it is not :D

Fun Facts #2

Posted by Ikhwan on January 25, 2008

It is really hard to yell “THIS IS SPARTA!” without spraying your spit.

Make ASP.NET Web Service Test Page Available Remotely

Posted by Ikhwan on January 25, 2008

ASP.NET Web Service test form

ASP.NET made publishing SOAP web services easier by automatically generating documentation page that can be accessed from the browser, just point it to the ASMX page. It also provide a web form so you can quickly test your web services by clicking a button without hacking up a web service client.

Unfortunately, if you access the page remotely, the form won’t show, with a notice “The test form is only available for requests from the local machine“. If you need it to be available remotely, add this code in your web.config.

<configuration>
	<system.web>
		<webServices>
			<protocols>
				<add name="HttpGet"/>
				<add name="HttpPost"/>
			</protocols>
		</webServices>
	</system.web>
</configuration>

This really helps a lot in testing. But you should probably remove that once your web service is published to production.

Reference:
http://geekswithblogs.net/juang/archive/2005/11/28/61437.aspx
http://msdn2.microsoft.com/en-us/library/b2c0ew36(VS.71).aspx

Resolving Paths Into Full URL

Posted by Ikhwan on January 22, 2008

In a web application, it’s generally a good idea on not to hard code your host name or domain name in your code (in HREF, SRC, etc), so you don’t need to change it when you deploy it to different machines.

This has been quite easy with ASP.NET, when you can always use the a relative path or by using the special “~” to indicate you application root. E.g. “~/Abc/Def.aspx” will be “/appbase/Abd/Def.aspx”.

But things gone awry when you want to include the host name in the URL. E.g. you want “~/Abc/Def.aspx” to become “http://localhost/appbase/Abd/Def.aspx”.

Relative path works well if you want your page to link to another page of yours. I have this need to transform relative URL to absolute, including the host name, and pass it to somewhere else, i.e. a remote web service.

Using System.Web.UI.Control.ResolveUrl(string) or the System.Web.VirtualPathUtility.ToAbsolute(string) works well if you just want an absolute path, but they does not include the host name. I can’t find any method that does, so I hack up own own.

public class WebHelper
{
	public static string ResolveToFullUrl(string url)
	{
		return ResolveToFullUrl(url, true);
	}

	// Starts with protocol
	protected static Regex rgxScheme = new Regex(@"^\w+://", RegexOptions.Compiled);

	public static string ResolveToFullUrl(string url, bool excludePortIf80)
	{
		HttpRequest r = HttpContext.Current.Request;
		if (r == null)
			throw new InvalidOperationException("This method only works in a web environment.");

		if (rgxScheme.IsMatch(url))
			return url;

		string withPort = (excludePortIf80 && r.Url.Port == 80) ? "" : ":" + r.Url.Port;
		return r.Url.Scheme + "://" + r.Url.Host + withPort +
				(new System.Web.UI.Control()).ResolveUrl(url);
	}
}

If you stop for a while and think about it, it’s kind of awkward that this kind of method is not readily available. If you know that I missed something and think I’m an idiot for re-inventing the wheel, please tell me. Don’t leave me in my idiocy.

On the other hand, I did learn something useful out of this. When you are not “in” a control (usualy a Page), Control.ResolveUrl() is not readily available to you, so VirtualPathUtility is a much handier. But I found that ToAbsolute() won’t work if you have strings like “Abc/Def.aspx” or “Abc/Def.aspx?id=123″. It seems to only work if the URL starts with “~” or “/” and doesn’t contain querystrings.

That’s why you can see in the code — if you did read it — I instantiate a Control and use it’s ResolveUrl() method. Instantiating stuff is a bit expensive, but I can’t find any other way to do it. You wiseguys might suggest that I use a static variable to hold an instance of Control and use it again and again, but that wouldn’t work (at least as what I wanted to).

The Control is instantiated “on-demand” so it will have the context at that point of time. Let’s say I pass in “../Ghi.aspx” when calling it from “http://localhost/appbase/Abc/Def.aspx”, it will produce “http://localhost/appbase/Ghi.aspx”.

If I save it as static, it will hold this context and later on if you pass “../Jkl.aspx” from “http://localhost/appbase/123/456/789.aspx”, you’ll get “http://localhost/appbase/Jkl.aspx” instead of “http://localhost/appbase/123/Jkl.aspx” that you wanted.

Still, I think this relative output like this is prone to confusion. But I prefer it to be this way.

Below are the some sample URLs and the results. I’m running it from http://localhost/appbase/TestFolder/Test.aspx.

Input

~/Abc
~/Abc/Def.aspx?ghi=jkl&mno=p|q
/Abc
Abc/Def.aspx
~/Abc/Def.aspx?ghi=jkl
/123/~/Abc
../Def.aspx
http://abc/def/ghi.php

Output

http://localhost/appbase/Abc
http://localhost/appbase/Abc/Def.aspx?ghi=jkl&mno=p|q
http://localhost/Abc
http://localhost/appbase/TestFolder/Abc/Def.aspx
http://localhost/appbase/Abc/Def.aspx?ghi=jkl
http://localhost/123/~/Abc
http://localhost/appbase/Def.aspx
http://abc/def/ghi.php

Do tell if I missed some other URL scheme.

Two Steps To Enjoy Life As A Programmer

Posted by Ikhwan on January 21, 2008

Step 1 : Quickly become as skillful as possible, like über-skilled or something, like get 10 man hours work done in 1 hour, and get yourself paid a filthy lotsa money.

Step 2 : Enjoy life.