Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

InvalidOperationException thrown regarding DotNetOpenAuth.IEmbeddedResourceRetrieval with Razor view

When my Razor view calls @Html.OpenIdSelector(... I get an InvalidOperationException:

The current IHttpHandler is not one of types: System.Web.UI.Page, DotNetOpenAuth.IEmbeddedResourceRetrieval. An embedded resource URL provider must be set in your .config file.

What exactly should I set in the config file?

like image 769
CD.. Avatar asked Jan 21 '11 09:01

CD..


2 Answers

Just NuGet the DotNetOpenAuth package. It will setup everything you need in your config file:

alt text

  1. Right click on the References of your web project in the solution explorer
  2. Add Library Package Reference...
  3. Click on the Online tab.
  4. In the search box type dotnetopenauth
  5. Click Install

Everything will be automatically setup and the correct assemblies will be downloaded from the internet and added as reference.

Here's how the web.config file looks like after performing this:

<?xml version="1.0" encoding="utf-8"?>
<!--
  For more information on how to configure your ASP.NET application, please visit
  http://go.microsoft.com/fwlink/?LinkId=152368
  -->
<configuration>
  <configSections>
    <section name="uri" type="System.Configuration.UriSection, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
    <section name="dotNetOpenAuth" type="DotNetOpenAuth.Configuration.DotNetOpenAuthSection" requirePermission="false" allowLocation="true" />
  </configSections>
  <connectionStrings>
    <add name="ApplicationServices" connectionString="data source=.\SQLEXPRESS;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|aspnetdb.mdf;User Instance=true" providerName="System.Data.SqlClient" />
  </connectionStrings>
  <appSettings>
    <add key="ClientValidationEnabled" value="true" />
    <add key="UnobtrusiveJavaScriptEnabled" value="true" />
  </appSettings>
  <system.web>
    <compilation debug="true" targetFramework="4.0">
      <assemblies>
        <add assembly="System.Web.Abstractions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
        <add assembly="System.Web.Helpers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
        <add assembly="System.Web.Routing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
        <add assembly="System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
        <add assembly="System.Web.WebPages, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
      </assemblies>
    </compilation>
    <authentication mode="Forms">
      <forms loginUrl="~/Account/LogOn" timeout="2880" />
    </authentication>
    <membership>
      <providers>
        <clear />
        <add name="AspNetSqlMembershipProvider" type="System.Web.Security.SqlMembershipProvider" connectionStringName="ApplicationServices" enablePasswordRetrieval="false" enablePasswordReset="true" requiresQuestionAndAnswer="false" requiresUniqueEmail="false" maxInvalidPasswordAttempts="5" minRequiredPasswordLength="6" minRequiredNonalphanumericCharacters="0" passwordAttemptWindow="10" applicationName="/" />
      </providers>
    </membership>
    <profile>
      <providers>
        <clear />
        <add name="AspNetSqlProfileProvider" type="System.Web.Profile.SqlProfileProvider" connectionStringName="ApplicationServices" applicationName="/" />
      </providers>
    </profile>
    <roleManager enabled="false">
      <providers>
        <clear />
        <add name="AspNetSqlRoleProvider" type="System.Web.Security.SqlRoleProvider" connectionStringName="ApplicationServices" applicationName="/" />
        <add name="AspNetWindowsTokenRoleProvider" type="System.Web.Security.WindowsTokenRoleProvider" applicationName="/" />
      </providers>
    </roleManager>
    <pages>
      <namespaces>
        <add namespace="System.Web.Helpers" />
        <add namespace="System.Web.Mvc" />
        <add namespace="System.Web.Mvc.Ajax" />
        <add namespace="System.Web.Mvc.Html" />
        <add namespace="System.Web.Routing" />
        <add namespace="System.Web.WebPages" />
      </namespaces>
    </pages>
  </system.web>
  <system.webServer>
    <validation validateIntegratedModeConfiguration="false" />
    <modules runAllManagedModulesForAllRequests="true" />
  </system.webServer>
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="1.0.0.0-2.0.0.0" newVersion="3.0.0.0" />
        <bindingRedirect oldVersion="1.0.0.0" newVersion="2.0.0.0" />
      </dependentAssembly>
    </assemblyBinding>
    <legacyHMACWarning enabled="0" />
  </runtime>
  <uri>
    <!-- The uri section is necessary to turn on .NET 3.5 support for IDN (international domain names),
         which is necessary for OpenID urls with unicode characters in the domain/host name. 
         It is also required to put the Uri class into RFC 3986 escaping mode, which OpenID and OAuth require. -->
    <idn enabled="All" />
    <iriParsing enabled="true" />
  </uri>
  <system.net>
    <defaultProxy enabled="true" />
    <settings>
      <!-- This setting causes .NET to check certificate revocation lists (CRL) 
                 before trusting HTTPS certificates.  But this setting tends to not 
                 be allowed in shared hosting environments. -->
      <!--<servicePointManager checkCertificateRevocationList="true"/>-->
    </settings>
  </system.net>
  <dotNetOpenAuth>
    <!-- This is an optional configuration section where aspects of dotnetopenauth can be customized. -->
    <!-- For a complete set of configuration options see http://www.dotnetopenauth.net/developers/code-snippets/configuration-options/ -->
    <openid>
      <relyingParty>
        <security requireSsl="false" />
        <behaviors>
          <!-- The following OPTIONAL behavior allows RPs to use SREG only, but be compatible
                         with OPs that use Attribute Exchange (in various formats). -->
          <add type="DotNetOpenAuth.OpenId.Behaviors.AXFetchAsSregTransform, DotNetOpenAuth" />
        </behaviors>
      </relyingParty>
    </openid>
    <messaging>
      <untrustedWebRequest>
        <whitelistHosts>
          <!-- Uncomment to enable communication with localhost (should generally not activate in production!) -->
          <!--<add name="localhost" />-->
        </whitelistHosts>
      </untrustedWebRequest>
    </messaging>
    <!-- Allow DotNetOpenAuth to publish usage statistics to library authors to improve the library. -->
    <reporting enabled="true" />
  </dotNetOpenAuth>
</configuration>

UPDATE:

You could implement a custom resource retrieval provider:

public class CustomResourceProvider : IEmbeddedResourceRetrieval
{
    public Uri GetWebResourceUrl(Type someTypeInResourceAssembly, string manifestResourceName)
    {
        return new Uri("http://www.google.com");
    }
}

and then register it in web.config:

<dotNetOpenAuth>
    <webResourceUrlProvider type="AppName.CustomResourceProvider, AppName" />
    ...
</dotNetOpenAuth>

But I would recommend you using the openid-selector library for generating login forms.

like image 186
Darin Dimitrov Avatar answered Oct 28 '22 16:10

Darin Dimitrov


I came across this problem when I was trying to get the NerdDinner OpenID working for MVC3/razor. The solution that has worked for me is:

Create this class in your solution: (this was found in one of the NerdDinner builds - http://nerddinner.codeplex.com/SourceControl/changeset/view/55257#1328982 (thanks to JasonHaley) for some reason, this file isn't in the latest build for NerdDinner MVC3/Razor

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using DotNetOpenAuth;
namespace <Your App>.Services
{
    public class EmbeddedResourceUrlService : IEmbeddedResourceRetrieval
    {

        private static string pathFormat = "{0}/{1}/Resource/GetWebResourceUrl?assemblyName={2}&typeName={3}&resourceName={‌​4}";
        //private static string pathFormat = "{0}/Resource/GetWebResourceUrl";

        public Uri GetWebResourceUrl(Type someTypeInResourceAssembly, string manifestResourceName)
        {
            if (manifestResourceName.Contains("http"))
            {
                return new Uri(manifestResourceName);
            }
            else
            {
                var assembly = someTypeInResourceAssembly.Assembly;

                // HACK
                string completeUrl = HttpContext.Current.Request.Url.ToString();
                string host = completeUrl.Substring(0,
                    completeUrl.IndexOf(HttpContext.Current.Request.Url.AbsolutePath));

                var path = string.Format(pathFormat,
                            host,
                            HttpContext.Current.Request.ApplicationPath.Substring(1),
                            HttpUtility.UrlEncode(assembly.FullName),
                            HttpUtility.UrlEncode(someTypeInResourceAssembly.ToString()),
                            HttpUtility.UrlEncode(manifestResourceName));

                return new Uri(path);
            }
        }
    }
}

Then in your web.config, add this line:

<webResourceUrlProvider type="<Your App>.Services.EmbeddedResourceUrlService, <Your App>" />

just put in the DotNetOpenAuth section

you will also need this route set up: ( Html.OpenIdSelectorScripts helper method throwing NullReferenceException )

    routes.MapRoute(
        "OpenIdDiscover",
        "Auth/Discover"
    );
like image 45
Beno Avatar answered Oct 28 '22 15:10

Beno