将客户端应用程序服务连接到自定义DB(而不是默认CE DB)

时间:2013-01-24 11:29:00

标签: c# asp.net sql-server

我有一个现有的C#ASP.NET Web应用程序,它使用成员资格和角色提供程序。这些表托管在同一个DB中,该DB包含所有应用程序表(托管在Azure中用于生产,本地SQLExpress用于开发)。

我想编写一个使用相同用户和角色信息的控制台应用程序。为此,我启用了客户端应用程序服务(在控制台应用程序上),并添加了一个新的Web服务,将这些服务暴露给控制台应用程序。

我可以在测试设置(包括控制台和winforms)中使用它,即Web服务创建自己的一组用户/角色,这些用户/角色从我读过的内容存储在本地文件中SQL CE数据库。

如何让Web服务从我的应用程序的数据库中读取?

为原始Web应用程序重新发布web.config:

<profile defaultProvider="DefaultProfileProvider">
  <providers>
    <add name="DefaultProfileProvider" type="System.Web.Providers.DefaultProfileProvider, System.Web.Providers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" connectionStringName="SecondBiteDBContext" applicationName="/" />
  </providers>
</profile>
<membership defaultProvider="DefaultMembershipProvider">
  <providers>
    <add name="DefaultMembershipProvider" type="System.Web.Providers.DefaultMembershipProvider, System.Web.Providers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" connectionStringName="SecondBiteDBContext" enablePasswordRetrieval="false" enablePasswordReset="true" requiresQuestionAndAnswer="false" requiresUniqueEmail="false" maxInvalidPasswordAttempts="10" minRequiredPasswordLength="6" minRequiredNonalphanumericCharacters="0" passwordAttemptWindow="10" applicationName="/" />
  </providers>
</membership>
<roleManager defaultProvider="DefaultRoleProvider" enabled="true">
  <providers>
    <add name="DefaultRoleProvider" type="System.Web.Providers.DefaultRoleProvider, System.Web.Providers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" connectionStringName="SecondBiteDBContext" applicationName="/" />
  </providers>
</roleManager>

Web服务的Web.config:

  <system.web.extensions>
    <scripting>
      <webServices>
        <authenticationService enabled="true" requireSSL="false"  />
        <profileService enabled="true"        readAccessProperties="WebSettingsTestText"        writeAccessProperties="WebSettingsTestText" />
        <roleService enabled="true"/>
      </webServices>
    </scripting>
  </system.web.extensions>
....
<system.web>
  <profile enabled="true" >
    <properties>
      <add name="WebSettingsTestText" type="string"
        readOnly="false" defaultValue="DefaultText"
        serializeAs="String" allowAnonymous="false" />
    </properties>
  </profile>
</system.web>

控制台应用的App.config:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
  </startup>
  <appSettings>
    <add key="ClientSettingsProvider.ServiceUri" value="http://localhost:31337/SecondBiteAppServices/Profile_JSON_AppService.axd" />
    <add key="ClientSettingsProvider.ConnectionStringName" value="DefaultConnection" />
  </appSettings>
  <connectionStrings>
    <add name="DefaultConnection" connectionString="Data Source=.\SQLExpress;Initial Catalog=SBAuto;MultipleActiveResultSets=True;Integrated Security=SSPI" />
  </connectionStrings>
  <system.web>
    <membership defaultProvider="ClientAuthenticationMembershipProvider">
      <providers>
        <add name="ClientAuthenticationMembershipProvider" type="System.Web.ClientServices.Providers.ClientFormsAuthenticationMembershipProvider, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" serviceUri="http://localhost:31337/SecondBiteAppServices/Authentication_JSON_AppService.axd" connectionStringName="DefaultConnection" savePasswordHashLocally="False" />
      </providers>
    </membership>
    <roleManager defaultProvider="ClientRoleProvider" enabled="true">
      <providers>
        <add name="ClientRoleProvider" type="System.Web.ClientServices.Providers.ClientRoleProvider, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" serviceUri="http://localhost:31337/SecondBiteAppServices/Role_JSON_AppService.axd" cacheTimeout="86400" connectionStringName="DefaultConnection" />
      </providers>
    </roleManager>
  </system.web>
</configuration>

我还没有指定可选的凭据提供程序,因为我没有使用表单 - 现在我无法通过硬编码调用validateuser()来成功。

使用项目属性 - &gt;服务标签 - &gt;高级按钮,我已指定一个指向所需数据库的自定义连接字符串。我知道它正在连接到我的数据库,因为有一段时间我得到了关于&#34;无效对象ApplicationProperties&#34;的例外情况。使用列PropertyName和PropertyValue在我的数据库中创建一个表来修复此问题。请注意,我已经在我的数据库上运行aspnet_regsql,我希望应该创建所需的表。

但是,它没有对驻留在该数据库中的用户进行验证检查 - 它运行得很干净(没有例外),但登录失败。基于上面的app.config结构,我推测自定义连接字符串仅适用于配置文件服务,而不是成员资格或角色服务? (只有配置文件服务[客户端设置提供程序]将连接字符串作为参数。)编辑:回顾一些文档,http://msdn.microsoft.com/en-us/library/bb384312似乎表明此自定义连接字符串仅用于存储脱机本地缓存内容。

使用项目 - &gt; asp.net配置(选择了Web服务项目),网站管理工具不允许我做任何有意义的事情来配置提供者或添加新提供者。

我无法追踪任何可以让我真正使用该数据库中的用户和角色的内容。有任何想法吗? (我对.net很新,所以很有可能我错过了一些东西,但是我在文档上遇到了很多麻烦并且从谷歌那里得到了不错的结果。)

一旦这个工作,我想在各个项目之间共享业务逻辑。目前逻辑位于主Web应用程序控制器方法中 - 显然我需要将其重构为共享层。鉴于涉及的对象是基于实体框架,这是否可能?

在我开始使用所有这些客户服务之前,我做了一个试验重构。我能够得到引用和编译的所有内容但是代码在执行的早期默默地失败了,我最好的猜测是所有与框架相关的所有内容都没有正确初始化 - 因此进入客户端应用服务。但是,我担心即使我让CAS进入,实体框架仍然会引起问题。

最后一个:如何在不同项目的配置文件之间共享配置元素(主要是连接字符串)?希望能够在开发和生产之间进行交换,而无需编辑多个文件。

编辑:黑客做了多少这样的事情? http://devpinoy.org/blogs/comgen/archive/2007/08/15/use-membership-api-in-winforms.aspx 即使与CAS没有直接关系,这是我能够找到的唯一真正有用的东西。好像我可以从我的主Web应用程序web.config中复制相应的行(其中包含指向我的DB&#39连接字符串的链接)。

谢谢!

更新25/1/13:尝试了上面链接编辑的建议选项,在上面列出的web.config元素中取代(尽管我还必须复制system.web。 providers.dll手动到bin / debug目录)。我可以干净地调用validateuser(),但它仍然不允许登录。我知道我正在访问我的数据库,因为SQL事件探查器中正在发生活动,并且正在更新用户表上的最后一个活动时间戳。当以CAS方式进行时,这不会发生。

更新25/1/13#2 - 过去4个小时试图调试它失败的原因,以及它让我快速疯狂。通过阅读代码(而不是调试),我所能说的是,在将提供的密码哈希与存储的密码哈希进行比较时失败了。我100%确定我提供了正确的用户名和密码。 Microsoft尚未发布system.web.providers.dll的代码,因此调试方面我无法进入membership .validateuser调用以外的任何内容,因为它调用DefaultMembershipProvider.ValidateUser。

Resharper将向我显示DefaultMembershipProvider的源代码(通过反编译),但我无法调试它。我在其他地方读过你可以将整个dll反编译成一个项目,删除对dll的引用,然后添加项目。

试图这样做,我遇到了以下问题:

Dis#允许我将该批次保存为项目,但它会产生看似错误的批次错误的源代码。它们似乎主要是语法错误,它没有正确的变量名称。导入项目VS时警告要更改目标.net版本,但这似乎没有做任何事情

Telerik JustDecompile允许我保存项目,但它没有包含.cs文件,该文件与system.web.providers.resources.providerresources.resx相符。我从Dis#中导入了.cs。然而,它仍然充满了错误,但不同的错误(尽管仍然有一些语法相关)并没有那么多。其中相当多的与其他system.x命名空间中的类有关。将该批次作为参考添加的毯子对任何事情都没有帮助。

ILSpy - 打开dll时,它列出了JustDecompile项目似乎引用的其他命名空间的部分。但是它只允许我逐个保存文件,而且我并不想尝试手动重建几十个dll文件的结构...

这是我第一次尝试反编译任何内容,但我能找到的所有内容似乎都表明了我应该做的事情(但他们当然没有提到我遇到的任何问题)具有)。关于下一步该做什么的任何想法?

关于我在OP中尝试过的Web服务的附注:我注意到aspnet_regsql.exe创建了一组重复的成员资格和角色表,前缀为&#34; aspnet _&#34;。例如。 aspnet_membership虽然我现有的应用程序/代码只使用普通会员资格。这清除了为什么Web服务无法读取我的数据,因为它正在检查不同的表。

我找到了一个博客(现在无法再找到这个链接)关于编写一些代码以在两个模式之间迁移数据的人,这表明不同的表集与不同版本的成员资格相关(等)提供者。因此,我假设在通用提供程序(system.web.providers)中看到的提供程序与客户端应用程序服务中使用的提供程序不同(并且不兼容),并且由我创建的Web服务公开。

1 个答案:

答案 0 :(得分:0)

提供答案,希望能为其他人带来很多痛苦。我没有得到上面提到的所有问题的答案,但这里有一些有用的信息。

  • 要使通用提供程序(system.web.providers.dll)连接到任何数据库,只需使用上面第一个web.config代码段中的相关配置行。这适用于任何类型的.NET项目的app.config(等)(就我所尝试过的那样)。确保添加对dll的引用,并且连接字符串包含在配置中。我将连接字符串重构为一个单独的配置,我将其链接到每个项目,以避免重复细节。
  • 旧样式提供程序与新的通用提供程序不兼容,因为它们的SQL模式不同。通过编写一些脚本来在模式之间进行转换,可以从旧的转换为新的。
  • BUT 在这样切换时,用于验证登录的哈希算法存在问题。您需要强制使用SHA1尝试在Web应用程序之外使用这些提供程序时<membership defaultProvider="DefaultMembershipProvider" hashAlgorithmType="SHA1">
  • 这就是我所询问的ValidateUser()调用失败的原因。 Connect上的这个错误是相关的:http://connect.microsoft.com/VisualStudio/feedback/details/734341/system-web-providers-defaultmembershipprovider-behavior-differs-from-sqlmembershipprovider-when-dealing-with-password-compatibility。由于这个错误,我的Web应用程序(使用通用提供程序)从一开始就一直在SHA1模式下运行 - 应该是HMACSHA256。默认HMACSHA256在使用控制台应用程序时正确应用,因此不匹配!
  • 其他有哈希算法配置问题的人:http://chriskinsmanblog.azurewebsites.net/2012/03/30/SystemWebProvidersDefaultMembershipProviderBehaviorChange.aspx
  • 然而,经过以上所有,我发现您不一定需要使用这些提供商。可以使实体框架无需登录或对提供者有任何引用即可正确执行。 (我希望我知道为什么在我开始所有这些混乱之前我无法使它工作。我知道我已经引用了相关的dll。)
  • 我仍然不知道为什么我无法令人满意地重新编译web.providers.dll。