简体   繁体   中英

How to configure a proxy class for an ASP.NET web service for flexible deployment to production

I inherited a web app at the Visual Studio 2003 level that placed all of its code for accessing SQL server in an ASMX web service. This web project had a web reference to the web service. I needed to bring the whole thing under source control, upgrade it to Vstudio 2008 and make a bunch of fixes and enhancements.

In doing this, I came across a neat article from Code Magazine emphasizing the advantages of "assembly separation" . It was written for WCF but it "inspired me" to:

  • remove the web reference from my main ASP.NET web application project
  • add a new project as a class library which I called ProxyZipeeeService
  • add a web reference in the ProxyZipeeeService project to point at the ZipeeeService project
  • add a reference in the main web app project to ProxyZipeeeService.DLL produced by building the project of the same name.

The things work and I guess there are some [performance?] advantages to separating things out like this but having described my structure, I need to get to my question/problem :

I run into lots of configuration problems when I deploy this into production that require me to make changes that are quite "awkward" and prone to me screwing things up. Here is my guess about what needs changing but I've searched extensively and cannot understand how:

The ProxyZipeeeService project with the web reference in it produces files as follows:

  • Reference.map.vb, ProxyZipeeeService.disco, ProxyZipeeeService.wsdl and app.config
  • on my development PC, the app.config file produced settings for the URL of localhost (as it should for my PC). Please view this XML entry at: http://pastebin.com/JtQCxT73
  • When I publish the web application project to the production web server, the URL for the webservice is "buried" inside the DLL for ProxyZipeeeService (which at this time is in the bin folder of the web app because it is referenced).

  • Because the prod web server is configured to recognize "host header files" [another question someday], the URL with localhost fails with a HTTP 400 Bad Request . The host header config requires anything related to this default website to use the domain http://www.zipeee.com/ZipeeeWebService/Zipeee.asmx

  • So to fix this, I have been having to "dismantle" my development project for ProxyZipeeeService - completely deleting the web reference, adding it back but this time make the dialog point to the WS on the production server (instead of letting it find the WS in "this solution" because that results in the problematic "localhost" setting).

  • Eventually I am able to push out to the prod server a web project referencing the proxy dll that won't run into this host header issue and it works without throwing the HTTP 400 error.

But there has to be a better way!

In short, the critical proxy dll cannot be configured with regard to the URL it should use the way I'm set up now. I've tried putting the applicationSettings entry from the app.config into the web.config of my web application project. I've also tried putting a variation on this into the appSettings section. Both of these attempts fail.

I hope I have been clear and not been too verbose. Please do not suggest major surgery like WCF because I can't bite off on that now for this project. Thank you for reading and thanks in advance for your help.

EDIT UPDATE: Changing URL in web app's WEB.CONFIG is not detected! Problem remains. Here is what I did:

  • Followed exactly what you said to do, lifting the settings from the app.config of the proxy to the web.config of the web app (establishing a new configuration section group that points to my setting from app.config.
  • The value in the proxy and now also in web.config reads as: http://localhost/ZipeeeWebService/Zipeee.asmx which is fine for testing on my dev PC
  • Before deploying all this to the production server, I thought I should test a bit. My first test was with the settings above and I set a breakpoint in the web service project and verified that the proxy had indeed come to localhost as the web.config entry intended and as expected.
    • Next (test case 2) I changed the web.config entry from localhost to www.zipeee.com which is where the production webservice the public facing web app uses.
    • I left the same breakpoint in the first web service call in place (expecting that it would not be hit because the intention was to use the URL specified in the web.config)
    • To my surprise, the breakpoint was hit and when I examined the URL via the Immediate Window, it showed it to be localhost (should have been to www.zipeee.com as desired in web.config).

Perhaps I have misunderstood what this approach should allow? Is there something I am missing? I did NOT rebuild the Proxy DLL (that remains with localhost) which I thought was the whole intent (ie to be able to control the URL in a sort of "late-binding" way via changes to the web.config of the web app).

I remain stumped. Hopefully, you could help me a bit more...Thanks.

EDIT UPDATE: 12 Oct

Thanks - I read your notes but I'm still confused. The ProxyZipeeeService project code is all generated from the web reference. Here is a snippet from the reference.vb file ( are you suggesting I modify this generated code? ):

Public Sub New()
        MyBase.New
        Me.Url = Global.ProxyZipeeeService.My.MySettings.Default.ProxyZipeeeService_WSZipeee_Zipeee
        If (Me.IsLocalFileSystemWebService(Me.Url) = true) Then
            Me.UseDefaultCredentials = true
            Me.useDefaultCredentialsSetExplicitly = false
        Else
            Me.useDefaultCredentialsSetExplicitly = true
        End If
    End Sub

    Public Shadows Property Url() As String
        Get
            Return MyBase.Url
        End Get
        Set
            If (((Me.IsLocalFileSystemWebService(MyBase.Url) = true)  _
                        AndAlso (Me.useDefaultCredentialsSetExplicitly = false))  _
                        AndAlso (Me.IsLocalFileSystemWebService(value) = false)) Then
                MyBase.UseDefaultCredentials = false
            End If
            MyBase.Url = value
        End Set
    End Property

By the way, could you comment on whether the whole idea of a separate assembly (proxy) for a web service is even a worthwhile thing. There may be some performance benefits (?) but these configuration issues are giving me fits.

EDIT-UPDATE 12 Oct - a bit later

After the last posting of the code from the generated file reference.vb, I spotted the problem! The declarations you had me place in the web app's web.config file were named:

section name="ProxyZipeeeService.Properties.MySettings"

while the reference.vb file refered to the setting as:

Me.Url = Global.ProxyZipeeeService.My.MySettings.Default.ProxyZipeeeService_WSZipeee_Zipeee

Changing the web config name to read as section name="ProxyZipeeeService. My .MySettings" has enabled the proxy to find the setting in the web app's web.config and I'm now able to "toggle" the web service URL through configuration parameters.

Thank you so much for your help. I am closing this now.

ps Do the "professionals" use Proxy classes as wrappers for web services like this?

You should place the configuration in the web.config of you web app, making a section group that references back to your ProxyZipeeeService project. To do so, copy both the sectiongroup and the actual applicationSettings from your ProxyZipeeeService to your web application:

  <configSections>
     <sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
        <section name="ProxyZipeeeService.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
     </sectionGroup>
  </configSections>
  <!--other stuff-->
  <applicationSettings>
     <ProxyZipeeeService.Properties.Settings>
        <!--your original appSettings-->
     </ProxyZipeeeService.Properties.Settings>
  </applicationSettings>

Then you can change the settings after your application has been deployed.

If all else fails, you could also make your ProxyZipeeeService library expose the URL as a public property, so it can be changed at runtime by the web application calling it.

I hope this was helpful.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM