Embedded Resources difference between VB.NET and C# projects
While I am developing a custom web control to extend the default validation summary I used some images within this control. One of the nice features and solutions came with ASP.NET 2.0 to address this problem is using web resources. So I embedded these images in my custom control assembly and used the Page.ClientScript.GetWebResourceUrl to resolve their URL's.
To do this task correctly you need to do 2 simple steps:
- First, you need to select whatever file you want to embed in your assembly and then set the Build Action property from its properties to Embed this is straight forward as saying 1, 2, 3.
- The second this we need to do is referencing that embedded resource so it could be retrieved as a web resources.This could be accomplished by adding WebResource attributes in the Assembly.info file.
In general to do this all we need is to add the web resource attribute like<Assembly: System.Web.UI.WebResource("EmbeddedResourcesVB.Sunset.jpg", "image/jpg")> the WebResource takes two parameters, the first one is the resource full name which following this convention: (Rootnamespace).(SubNameSapce).(Filename).(Extension) and the second parameter is the MIEM file type of the resource
So what's wrong?
This looks very simple but why all problems occurred? What is the error prone thing which make all these posts and articles on the web!! To identify this we can say there is some issue regarding the way that VB.NET projects and C# projects being organized. Is that true? Yes that's true!!
To figure out this issue I created simple solution conations a VB.NET project and a C# project. and add an image to each of them as our embedded resource. I changed the Root Namespace property for each project to make it clear that the assembly name has nothing to do with WebResource name. By default the Root Namespace == assembly name but in some certain scenarios you need to change that so by choosing the project properties you can change the assembly name property and the RootNamespace property.
After building our solution let's have a closer look to the embedded resources after being compiled into assembly. So let's open EmbResVB.dll and EmbResCSharp.dll using Reflector. If you take a quick look to the image below you can note that the Sunset.jpg image resource name differs from the Vb.Net assembly to the C# one.
But we said that the resource name should follow this convention: (RootNameSpace).(SubNameSapce).(Filename).(Extension) so what's happens??!!
Here's what happen: in the C# projects if you add a new class to your solution you will find that the IDE put's this file in a namespace regarding to the solution folders hierarchy. But in VB.NET projects this is not occur. Let's take the ImagesUrl class as example, this class which exists's under the images folder in our testing C# and VB.NET projects but it will look like this by default in C#:
using System;
using System.Collections.Generic;
using System.Text;
namespace EmbeddedResourcesCSharp.Images
{
public class ImagesURL
{
}
}
while in the VB.NET project it will be added to the root namespace by default:
Public Class ImagesUrl
Sub New()
Technorati Tags: asp.net,embbede resources,.Net
End Sub
End Class
C# is doing this because of the VC# wizards which work in the background when you add new items to your project. Here's an article for one of the VS team descriping this issue http://blogs.msdn.com/joen/archive/2004/03/15/90002.aspx.
Anyway it seems that C# IDE is handling the other files like our image in the same way. So our Sunset.jpg image have been listed under the images namespace which actually it's parent folder name. But in the VB.NET project Sunset.jpg is being added to the root namespace never mind in any sub folder it exists.
Ok, that's it, the reason of all the misunderstanding. Many VB.NET developers reading posts or articles about embedded resources written in C# and they didn't notice the different in embedded resources names between the VB.NET and C# projects.
The result
In a C# project embedded resources names follows this convention (RootNampeSpace).(Path).(FileName).(Extension) where Path is the folders path in which this resource exist Root/Folder/SubFolder/.../ResourceFile .In A VB.NET project embedded resources names follows this convention (RootNampeSpace).(FileName).(Extension) and the resource path does not affect its name.
Hope that help. Happy asp.net
Huthaifa