7

I would like to handle requests differently depending upon the MIME type. For example, I have PDF's, images and other media files that I would like to prohibit access to based on their respective MIME types. Any ideas on how to do this? Thanks for the help.

I should also note that accessing the Windows registry is not an option for my application.

mkelley33
  • 5,323
  • 10
  • 47
  • 71

5 Answers5

11

.NET's mime-type mappings are stored in the System.Web.MimeMapping class which offers the GetMimeMapping method.

Prior to .NET 4.5, this class was marked as internal, and thus not available to your code. In that case the best you can do is steal the list, which you can get using Reflector and decompile the static constructor (cctor).

If taking that approach, you may be better off simply creating a list of supported extensions and their mime type and storing it on a dictionary. (The list inside MimeMapping is a tad verbose)

Snixtor
  • 4,239
  • 2
  • 31
  • 54
Richard Szalay
  • 83,269
  • 19
  • 178
  • 237
  • That's exactly the route I took. I'm sure I missed some extensions, but they would most likely be corner cases best dealt with as they arise to satisfy the "being productive/working software" requirement LOL. Thanks for the suggestion! I never knew about the MimeMappings. Very cool! – mkelley33 Aug 19 '09 at 20:49
  • 3
    As of 4.5, this class has gone public! With the convenient `GetMimeMapping(string fileName)` method. - http://msdn.microsoft.com/en-us/library/system.web.mimemapping.getmimemapping.aspx – Snixtor Feb 08 '13 at 01:50
9

I had a similar problem a few month ago and solved it with this simple wrapper-class around System.Web.MimeMapping (as mentioned by Richard Szalay):

/// <summary>
/// This class allows access to the internal MimeMapping-Class in System.Web
/// </summary>
class MimeMappingWrapper
{
    static MethodInfo getMimeMappingMethod;

    static MimeMappingWrapper() {
        // dirty trick - Assembly.LoadWIthPartialName has been deprecated
        Assembly ass = Assembly.LoadWithPartialName("System.Web");
        Type t = ass.GetType("System.Web.MimeMapping");

        getMimeMappingMethod = t.GetMethod("GetMimeMapping", BindingFlags.Static | BindingFlags.NonPublic);
    }

    /// <summary>
    /// Returns a MIME type depending on the passed files extension
    /// </summary>
    /// <param name="fileName">File to get a MIME type for</param>
    /// <returns>MIME type according to the files extension</returns>
    public static string GetMimeMapping(string fileName) {
        return (string)getMimeMappingMethod.Invoke(null, new[] { fileName });
    }
}
BenMorel
  • 34,448
  • 50
  • 182
  • 322
J. Random Coder
  • 1,322
  • 11
  • 21
  • 1
    Any problem with avoiding the dirty hack by referencing a public type? `Assembly.GetAssembly(typeof(System.Web.HttpApplication))`. As long as the method and referenced type don't change or disappear, that is... ? – Nelson Rothermel Jun 30 '10 at 20:13
  • 6
    I like your variable name for Assembly. – Ivan G. Aug 19 '10 at 15:06
8

Cross-posting from Why would Reflection search suddenly not find anything?

The good news is that the MimeMapping class and its GetMimeMapping method seem like they might be made public in .NET 4.5.

However, this means that the code given in the above answer would break, since it’s only searching for GetMimeMapping among NonPublic methods.

To ensure compatibility with .NET 4.5 (but preserve functionality in .NET 4.0 and earlier), change…

getMimeMappingMethod = t.GetMethod("GetMimeMapping", 
    BindingFlags.Static | BindingFlags.NonPublic);

…to:

getMimeMappingMethod = t.GetMethod("GetMimeMapping",
    BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public);
Community
  • 1
  • 1
Douglas
  • 53,759
  • 13
  • 140
  • 188
  • nice one..although I don't get it. I am still on .NET 4 and yet the framework seems to behave like you described (which is like in .NET 4.5)..very strange – mare Jun 21 '12 at 22:50
  • 1
    @mare you may have .NET 4.5 installed -- it's an in-place upgrade so the assemblies will have the new code at runtime but VS restricts you at compile time to the code available to .NET 4.0. – JT. Feb 11 '13 at 01:05
1

This information is in the registry, in HKEY_CLASSES_ROOT\<file_extension>\Content Type

using(var key = Registry.ClassesRoot.OpenSubKey(".htm"))
{
    string mimeType = key.GetValue("Content Type") as string;
}
Thomas Levesque
  • 286,951
  • 70
  • 623
  • 758
0

If I am understanding your question properly, you are serving static files and want to be able to do processing on a static file request in order to decide whether or not the user has access to that file. (based on MIME type)

If you map all files requests through a custom IHttpHandler (see the handlers section of your web.config file), you should be able to accomplish this.

In ProcessRequest (or BeginProcessRequest if you implement an asynchronous handler), you can call HttpContext.Current.Server.MapPath("~" + HttpContext.Current.Request.Path) (might be a better way to do that) to get the current static file being requested.

You can then analyze the extension of that file to make your decision.

Not sure if thats what you want, but hopefully it helps

LorenVS
  • 12,597
  • 10
  • 47
  • 54
  • That's very close to what I want, but I was hoping there was a more automatic way of doing it, rather than analyzing the extension. Something more along the lines of Request.MIMEType. Thank you for your input! – mkelley33 Aug 19 '09 at 20:44