Is there a way to get ALL the MIME types instead of wrinting a huge case statement? - asp.net

I want to populate
Response.ContentType = "text/plain";
From somewhere in the server/web/dictionary ALL possible MIME types according to file extension:
public string GetMimeType(string extension)
{
//This is what I am looking for.
}
Also, I have to rename the file (at least if going to be downloaded, so I have to know in advance if it's going to be opened or not.

You can store the mimetype when the file is uploaded ( FileUpload.PostedFile.ContentType ) and send that when the file is requested.

Umm... why? You're not going to be returning content of every possible type, are you?
Here's a list of common types: http://www.webmaster-toolkit.com/mime-types.shtml. There is no list that would include "ALL" types simply because any application vendor can create a custom one and associate it with a custom extension.

It's going to depend on your platform. Here's one for C# and IIS: http://blog.crowe.co.nz/archive/2006/06/02/647.aspx
In Powershell it's a one-liner:
([adsi]"IIS://localhost/MimeMap").MimeMap

The code in the link posted by Richard:
// Maintain a sorted list to contain the MIME Types
SortedList sl = new SortedList();
Console.WriteLine("IIS Mime Map - c#");
Console.WriteLine();
// Serve to connect to...
string ServerName = "LocalHost";
// Define the path to the metabase
string MetabasePath = "IIS://" + ServerName + "/MimeMap";
// Note: This could also be something like
// string MetabasePath = "IIS://" + ServerName + "/w3svc/1/root";
try
{
// Talk to the IIS Metabase to read the MimeMap Metabase key
DirectoryEntry MimeMap = new DirectoryEntry(MetabasePath);
// Get the Mime Types as a collection
PropertyValueCollection pvc = MimeMap.Properties["MimeMap"];
// Add each Mime Type so we can display it sorted later
foreach (object Value in pvc)
{
// Convert to an IISOle.MimeMap - Requires a connection to IISOle
// IISOle can be added to the references section in VS.NET by selecting
// Add Reference, selecting the COM Tab, and then finding the
// Active DS Namespace provider
IISOle.MimeMap mimetypeObj = (IISOle.MimeMap)Value;
// Add the mime extension and type to our sorted list.
sl.Add(mimetypeObj.Extension, mimetypeObj.MimeType);
}
// Render the sorted MIME entries
if (sl.Count == 0)
Console.WriteLine("No MimeMap entries are defined at {0}!", MetabasePath);
else
foreach (string Key in sl.Keys)
Console.WriteLine("{0} : {1}", Key.PadRight(20), sl[Key]);
}
catch (Exception ex)
{
if ("HRESULT 0x80005006" == ex.Message)
Console.WriteLine(" Property MimeMap does not exist at {0}", MetabasePath);
else
Console.WriteLine("An exception has occurred: \n{0}", ex.Message);
}

// Convert to an IISOle.MimeMap - Requires a connection to IISOle
// IISOle can be added to the references section in VS.NET by selecting
// Add Reference, selecting the COM Tab, and then finding the
// Active DS Namespace provider
According to my googling: (lost the links, sorry)
The "Active DS IIS Namespace Provider" is part of the IIS installation.
After you install IIS you will see that in the list of options.
If you don't see it should be located at C:\windows\system32\inetsrv\adsiss.dll.
To install IIS:
click Start, Settings, Control Panel, Add or Remove Programs, Add or Remove Windows Components, select Internet Informatoin Services (IIS).
Most of the code I've seen uses some combination of these:
using System.IO;
using System.DirectoryServices; // Right-click on References, and add it from .NET
using System.Reflection;
using System.Runtime.InteropServices;
using System.Collections;
using IISOle;
using System.Collections.Specialized;
The Active DS Namespace might be under the COM tab when adding the reference.

I've written a small class based on the webmaster-toolkit.com list. This is to avoid using COM and the IIS route or any IIS references.
It uses an XML serialized list which contains about 400 mimetypes, so is usually more than enough unless you have really obscure mimetypes. In that case you can just add to the XML file.
The full solution can be found here. Here's a sample:
class Program
{
static void Main(string[] args)
{
var list = MimeType.Load();
MimeType mimetype = list.FirstOrDefault(m => m.Extension == "jpg");
}
}

Related

Localization in ASP.NET MVC 4 using App_GlobalResources

I am trying to accomplish two things:
Localize the “built-in” error messages for “FieldMustBeDate” and "FieldMustBeNumeric".
Localize some of the other error messages you would encounter, for example, "PropertyValueRequired".
By using http://forums.asp.net/t/1862672.aspx/1 for problem 1 and MVC 4 ignores DefaultModelBinder.ResourceClassKey for problem 2 I have managed to get both working locally.
However as soon as I publish to a website, the “built-in” error messages defaults back to English while the other error messages stay localized.
I have read several places that using the App_GlobalResources should be avoided, however I am unable to accomplish problem 1 without using this.
I have created a .resx file with the name “WebResources.resx”, set the Build Action to “Embedded”, set the Copy to Output Directory to “Do no Copy”, set the Custom Tool to “PublicResXFileCodeGenerator” and set the Custom Tool Namespace to “Resources”.
The Project itself is set to only Publish files that are needed.
My Global.asax.cs contains the following (relevant) code:
ClientDataTypeModelValidatorProvider.ResourceClassKey = "WebResources";
DataAnnotationsModelValidatorProvider.RegisterAdapter(
typeof(RequiredAttribute),
typeof(MyRequiredAttributeAdapter));
And the class MyRequiredAttributeAdapter contains the following code:
public class MyRequiredAttributeAdapter : RequiredAttributeAdapter
{
public MyRequiredAttributeAdapter(
ModelMetadata metadata,
ControllerContext context,
RequiredAttribute attribute
)
: base(metadata, context, attribute)
{
if (attribute.ErrorMessageResourceType == null)
{
attribute.ErrorMessageResourceType = typeof(Resources.WebResources);
}
if (attribute.ErrorMessageResourceName == null)
{
attribute.ErrorMessageResourceName = "PropertyValueRequired";
}
}
}
This is working locally however does anyone have any idea on how to get the "built in" messages to work after this is published?
Thank you for your help!
Best regards,
Andreas
I figured this one out myself. If you are trying to accomplish the above you must separate the localized error messages.
Create a *.resx file for the other error messages fx "PropertyValueRequired" and set the Build Action to “Embedded”, set the Copy to Output Directory to “Do no Copy”, set the Custom Tool to “PublicResXFileCodeGenerator” and set the Custom Tool Namespace to “Resources”.
In my case I have moved "PropertyValueRequired" to a file called LocalDanish.resx (still in the App_GlobalResources folder) and changed the line in my "MyRequiredAttributeAdapter" from
attribute.ErrorMessageResourceType = typeof(Resources.WebResources);
to
attribute.ErrorMessageResourceType = typeof(Resources.LocalDanish);
In order to get the "built in" error messages to work, you must create two *.resx files. I have created WebResources.resx and WebResources.da.resx. Do NOT change anything, leave the settings on them on default (Build Action to "Content", etc.). I guess the website automatically looks for the *.da.resx files in my case because I have set the globalization in my WebConfig:
<globalization uiCulture="da-DK" culture="da-DK"/>
Hope this helps anybody.
Best regards,
Andreas
I have made some minor additions to the original post, which didn't translate all messages in my case.
(String length and invalid property values)
Follow the above steps, to create the *.resx files, set their properties, and then set the locale in web.config, as described by Andreas.
Then create a couple of adapters:
// As described in original post:
public class LocalizedRequiredAttributeAdapter : RequiredAttributeAdapter
{
public LocalizedRequiredAttributeAdapter(
ModelMetadata metadata,
ControllerContext context,
RequiredAttribute attribute
)
: base(metadata, context, attribute)
{
if (attribute.ErrorMessageResourceType == null)
attribute.ErrorMessageResourceType = typeof(Resources.Resources);
if (attribute.ErrorMessageResourceName == null)
attribute.ErrorMessageResourceName = "PropertyValueRequired";
}
}
// Addition to original post:
public class LocalizedStringLengthAttributeAdapter : StringLengthAttributeAdapter
{
public LocalizedStringLengthAttributeAdapter(
ModelMetadata metadata,
ControllerContext context,
StringLengthAttribute attribute
)
: base(metadata, context, attribute)
{
if (attribute.ErrorMessageResourceType == null)
attribute.ErrorMessageResourceType = typeof(Resources.Resources);
if (attribute.ErrorMessageResourceName == null)
attribute.ErrorMessageResourceName = "StringLengthAttribute_ValidationError";
}
}
And in Global.asax.cx:
// Addition to original post: (Used for "PropertyValueInvalid")
DefaultModelBinder.ResourceClassKey = "Resources";
// As described in original post:
ClientDataTypeModelValidatorProvider.ResourceClassKey = "Resources";
DataAnnotationsModelValidatorProvider.RegisterAdapter(typeof(RequiredAttribute), typeof(LocalizedRequiredAttributeAdapter));
DataAnnotationsModelValidatorProvider.RegisterAdapter(typeof(StringLengthAttribute), typeof(LocalizedStringLengthAttributeAdapter));

Tridion 2009 SP1: Is it possible to publish a .htaccess file?

I am using ISAPI rewrite on a project and would like to know if it is possible to publish a .htaccess file from Tridion?
I have tried creating a Page Template with the .htaccess extension but can't create a page with no name.
Any ideas?
Could I use a C# TBB to change the page name?
I would also choose to use a binary to achieve this, but if you want to manage the htaccess file using text, rather than as a multimedia component, you can push a binary into your package using the following technique:
1) Push the text of the Htaccess file into the package with an accessible name (i.e. Binary_Text)
2) Use code similar to the following to create a text file from the text in the variable and add it to the package
class publishStringItemAsBinary : ITemplate
{
public void Transform(Engine engine, Package package)
{
TemplatingLogger log = TemplatingLogger.GetLogger(typeof(publishStringItemAsBinary));
TemplateUtilities utils = new TemplateUtilities();
System.IO.Stream inputStream = null;
try
{
string strInputName = package.GetValue("InputItem");
string strFileName = package.GetValue("strFileName");
string sg_Destination = package.GetValue("sg_Destination");
string itemComponent = package.GetValue("mm_Component");
inputStream = new MemoryStream(Encoding.UTF8.GetBytes(package.GetValue(strInputName)));
log.Debug("InputObject:" + strInputName);
log.Debug("Filename for binary:" + strFileName);
log.Debug("Destination StructureGroup:" + sg_Destination);
Publication contextPub = utils.getPublicationFromContext(package, engine);
TcmUri uriLocalSG = TemplateUtilities.getLocalUri(new TcmUri(contextPub.Id), new TcmUri(sg_Destination));
TcmUri uriLocalMMComp = TemplateUtilities.getLocalUri(new TcmUri(contextPub.Id), new TcmUri(itemComponent));
StructureGroup sg = (StructureGroup)engine.GetObject(uriLocalSG);
Component comp = (Component)engine.GetObject(uriLocalMMComp);
String sBinaryPath = engine.PublishingContext.RenderedItem.AddBinary(inputStream, strFileName, sg, "nav", comp, "text/xml").Url;
//Put a copy of the path in the package in case you need it
package.PushItem("BinaryPath", package.CreateStringItem(ContentType.Html, sBinaryPath));
}
catch (Exception e)
{
log.Error(e.Message);
}
finally
{
if (inputStream != null)
{
inputStream.Close();
}
}
}
}
I think the code is pretty self explanatory. This publishes a binary of type text/xml, but there should be no issue converting it to do a plain text file.
I think you can use multimedia component to store your .htaccess. Even if you will not be able to upload file without name (Windows limitation), you will be able to change filename later, by modifying BinaryContent.Filename property of multimedia component. You can then publish this component seperately, or use AddBinary method in one of your templates.
There's also a user schema where you can change some other rules: "\Tridion\bin\cm_xml_usr.xsd", but you will not be able to allow empty filenames

How to Get the ConnectionString that the Membership Provider is using?

... and not by reading it from the config file! Nor inferring it from anyplace other than be reading exactly what the Membership Provider is itself using. Call me paranoid.
The first data access in my application is an access to the membership provider. The vast majority of connectivity issues have been where the application is deployed to staging or production with a connection string from development, so I'd like to change this:
MembershipUser me = Membership.GetUser();
to this:
MembershipUser me;
try
{
me = Membership.GetUser();
}
catch ( SqlException E )
{
Response.Write( "SQL Error " + E.Message + ".<br />" );
Response.Write( "Connection String: " + Membership.Provider.WHAT? + "<br />" );
}
Seems so obvious, but every reference I find instructs me to use the ConfigurationManager, which is what I specifically don't want to do. Although I concede that such may be my only option, and a satisfactory one at that.
I'm perfectly willing to accept the possibility that my question is on par with this:
int i;
try
{
i = 42;
}
catch ( Exception e )
{
Response.Write( "Error assigning literal to integer." );
}
If this is the case, please comment accordingly.
I don't believe there is a direct property that you can use that will give you the connection information. One thing you could do though is subclass your chosen membership provider and implement your own properties to give you the info.
It's generally considered a bad idea to surface connection strings in the UI (i.e. poor security) which is why you won't find readily available properties to pass on the value from classes that have read it from the config file.
You may want to consider addressing the root cause of the problem which is related to deployment. This problem is easily solved by using different configuration files for development, staging and production. Visual Studio has built-in support for automatically managing the deployment of the appropriate config file. Full details here:
http://blogs.msdn.com/b/webdevtools/archive/2009/05/04/web-deployment-web-config-transformation.aspx
Hi Here is a way to get connection string from or by the specified Provider Name (ex MySQL provider).
using MySql.Data.MySqlClient;
using MySql.Data;
using MySql.Web.Security;
using System.Collections.Specialized;
using System.Reflection;
void SomeFunction()
{
Type t = Membership.Provider.GetType();
FieldInfo fi = null;
while (fi == null && t != null)
{
fi = t.GetField("connectionString", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
t = t.BaseType;
}
MySql.Web.Security.MySQLMembershipProvider a =(MySql.Web.Security.MySQLMembershipProvider)Membership.Provider;
string Connection_String_Value= fi.GetValue(a).ToString();
}
By replace 'connectionString' with other Non-Public field name You
can Access its Value too.
By replacing Provider(default) with
Membership.Providers["Name_Of_Your_Provider"] you can get its
connection string too.

Getting the mime w/o using urlmon

I was using urlmon to find the MIME of files however it didnt go well when i couldn't get the correct mime of css files and more SWFs. What can i use to get the file mime?
Hmm, I am not sure I completely understand your question, but if you want to do some sort of look up against a master list you can look at the IIS Metabase
using (DirectoryEntry directory = new DirectoryEntry("IIS://Localhost/MimeMap")) {
PropertyValueCollection mimeMap = directory.Properties["MimeMap"];
foreach (object Value in mimeMap) {
IISOle.MimeMap mimetype = (IISOle.MimeMap)Value;
//use mimetype.Extension and mimetype.MimeType to determine
//if it matches the type you are looking for
}
}

ASP.NET/IIS6: How to search the server's mime map?

i want to find the mime-type for a given file extension on an IIS ASP.NET web-server from the code-behind file.
i want to search the same list that the server itself uses when serving up a file. This means that any mime types a web-server administrator has added to the Mime Map will be included.
i could blindly use
HKEY_CLASSES_ROOT\MIME\Database\Content Type
but that isn't documented as being the same list IIS uses, nor is it documented where the Mime Map is stored.
i could blindly call FindMimeFromData, but that isn't documented as being the same list IIS uses, nor can i guarantee that the IIS Mime Map will also be returned from that call.
Here is another similar implementation, but doesn't require adding the COM reference - it retrieves the properties through reflection instead and stores them in a NameValueCollection for easy lookup:
using System.Collections.Specialized; //NameValueCollection
using System.DirectoryServices; //DirectoryEntry, PropertyValueCollection
using System.Reflection; //BindingFlags
NameValueCollection map = new NameValueCollection();
using (DirectoryEntry entry = new DirectoryEntry("IIS://localhost/MimeMap"))
{
PropertyValueCollection properties = entry.Properties["MimeMap"];
Type t = properties[0].GetType();
foreach (object property in properties)
{
BindingFlags f = BindingFlags.GetProperty;
string ext = t.InvokeMember("Extension", f, null, property, null) as String;
string mime = t.InvokeMember("MimeType", f, null, property, null) as String;
map.Add(ext, mime);
}
}
You can very easily cache that lookup table, and then reference it later:
Response.ContentType = map[ext] ?? "binary/octet-stream";
Here's one I made earlier:
public static string GetMimeTypeFromExtension(string extension)
{
using (DirectoryEntry mimeMap =
new DirectoryEntry("IIS://Localhost/MimeMap"))
{
PropertyValueCollection propValues = mimeMap.Properties["MimeMap"];
foreach (object value in propValues)
{
IISOle.IISMimeType mimeType = (IISOle.IISMimeType)value;
if (extension == mimeType.Extension)
{
return mimeType.MimeType;
}
}
return null;
}
}
Add a reference to System.DirectoryServices and a reference to Active DS IIS Namespace Provider under the COM tab. The extension needs to have the leading dot, i.e. .flv.
IIS stores the MIME information in its own database. Searching for "MimeMap IIS" on the internet will reveal how to read it or even change it. See for example C# - How to display MimeMap entries to the console from an instance of IIS.

Resources