Search code examples
c#web-servicesihttphandler

The URI prefix is not recognized OnDownloadStringCompleted


I've got a problem with simply method whch gets string from asp.net 4 ashx. I'm running below methods from silverlight application which is being hosted by this asp.net application.

private void LoadPlugins()
{
    var serviceAddress = _baseAddress
        + "PluginsService.ashx?"
        + DateTime.Now.Ticks;

    var client = new WebClient();
    client.DownloadStringCompleted += client_DownloadStringCompleted;
    client.DownloadStringAsync(new Uri(serviceAddress));
}

void client_DownloadStringCompleted(
    object sender,
    DownloadStringCompletedEventArgs e)
{
    var plugins = e.Result.Split(
        new string[] { Environment.NewLine },
        StringSplitOptions.RemoveEmptyEntries);
    foreach (var plugin in plugins)
    {
        AddXap(_baseAddress + plugin);
    }
}

PluginsService.ashx.cs:

namespace MefPlugins.Web
{
    /// <summary>
    /// Summary description for PluginsService
    /// </summary>
    public class PluginsService : IHttpHandler
    {
        private const string PluginsFolderName = "Plugins/";

        public void ProcessRequest(HttpContext context)
        {
            //var pluginFolder = new DirectoryInfo(
            //    HttpContext.Current.Server.MapPath(
            //    PluginsFolderName));
            //var response = new StringBuilder();

            //if (pluginFolder.Exists)
            //{
            //    foreach (var xap in pluginFolder.GetFiles("*.xap"))
            //    {
            //        response.AppendLine(
            //            PluginsFolderName + xap.Name);
            //    }
            //}

            var response = new StringBuilder();
            response.Append("test");
            context.Response.ContentType = "text/plain";
            context.Response.Write(response);
        }

        public bool IsReusable
        {
            get
            {
                return false;
            }
        }
    }
}

I get an error:

System.Reflection.TargetInvocationException was unhandled by user code Message=An exception occurred during the operation, making the result invalid. Check InnerException for exception details. StackTrace: w System.ComponentModel.AsyncCompletedEventArgs.RaiseExceptionIfNecessary() w System.Net.DownloadStringCompletedEventArgs.get_Result() w MefPlugins.MainPage.client_DownloadStringCompleted(Object sender, DownloadStringCompletedEventArgs e) w System.Net.WebClient.OnDownloadStringCompleted(DownloadStringCompletedEventArgs e) w System.Net.WebClient.DownloadStringOperationCompleted(Object arg) InnerException: System.Net.WebException Message=An exception occurred during a WebClient request. InnerException: System.NotSupportedException Message=The URI prefix is not recognized. StackTrace: w System.Net.WebRequest.Create(Uri requestUri) w System.Net.WebClient.GetWebRequest(Uri address) w System.Net.WebClient.DownloadStringAsync(Uri address, Object userToken) InnerException:

Where could be a bug? this is an example from http://www.galasoft.ch/sl4u/code/chapter20/20.02-Mef/MefPlugins.zip


Solution

  • The reason for the error lies in which project is startup object selected as your startup project.

    When your startup project is the MefPlugins projec (a Silverlight Project)t, the project settings indicate that a web page should be dynamically created to host your Silverlight application (right click on project, select Properties and go to the Debug tab).

    The problem you runing into has to do with the location that is used as a prefix for the PluginsService.ashx file. The _baseAddress is set by in the main page constructor by the following code:

    var xapUri = App.Current.Host.Source;
    _baseAddress = xapUri.AbsoluteUri
                         .Substring(0, xapUri.AbsoluteUri.IndexOf(xapUri.AbsolutePath)) 
                   + "/";
    

    This means that the Uri of the xap file is used to determine the base uri. Now, as the project is using a dynamically generated container page - which is located on your hard drive and started from there - the above code takes the filesystem root is the _baseAddress. Obviously, the code will not find the PluginsService.ashx page, as it is not there.

    Additionally, an .ashx file needs some form of http listener that routes the request from a port to your .ashx page. The listener can be a web server like IIS or the development web server, or some listener you implemented yourself.

    To solve the problem make the MefPlugins.Web project your startup project and set MefPluginsTestPage.aspx as your startup page. Now _baseAddress should be something simlilar to http://localhost:6584/.

    When this base address is now used to find the PluginsService.ashx page, it will result in a correct URI for the resource (http://localhost:6584/PluginsService.ashx in our case).

    In general .ashx files are extensions to a web service (IIS, debug web server, or even some own implementation) they are not part of the silverlight client.