locked
Cannot make WCF Data Services work on a clustered hosted website RRS feed

  • Question

  • Any help on this would be truly appreciated. This has been driving me nuts for several weeks now.

    I have, an MVC 4 website situated on a Clustered Windows Hosting architecture with a MySQL database driving the Application.

    This works absolutely fine. If I want to access the MySQL database via any I.P. other than via the MVC application then I have to register the I.P. address of the system I'm on before trying to access. 

    What I want to do, and have been trying to do for weeks, is access the MySQL database through a WPF application, in order to give slightly more access than through my MVC4.

    Because my I.S.P. doesn't use fixed I.P. addresses, in order to make this connection I would have to go onto the website settings each time I wanted to access it and re-register my current I.P. address.

    After some investigation I figured that the best way to achieve this kind of access without having to re-register every time is via a WCF Data Service.

    I have followed every single tutorial that I could find and none of them work with my scenario. They all refer to localhost, and I am trying to publish to a domain where I have no access to IIS settings at all.

    What I have done so far is the following.

    Created an empty MVC 4 Application in order to host my WCF Data Service. (called MyServices)

    Added an Entity Data Model which connects to the MySQL database.

    Added a WCF Data Service to the MVC 4 Application with the following InitializeService syntax (Called CRMService)

        public class CRMService : DataService<CRMEntities>
        {
            // This method is called only once to initialize service-wide policies.
            public static void InitializeService(DataServiceConfiguration config)
            {
                // TODO: set rules to indicate which entity sets and service operations are visible, updatable, etc.
                // Examples:
                // config.SetEntitySetAccessRule("MyEntityset", EntitySetRights.AllRead);
                config.SetEntitySetAccessRule("*", EntitySetRights.AllRead | EntitySetRights.AllWrite);
                config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V2;
            }
        }

    I have tried, after this publishing it to a subdomain on my domain called http://services.mydomain.com and then trying to add a service reference in WPF, but this always comes up with errors.

    Then following advice from one of the tutorials that I have been following, I added the MVC4 MyServices project to my WPF project and discovering the service, which worked beautifully in actually finding the service.

    Then, in my WPF project, I used the following code to test it.

    Uri uri = new Uri("http://services.mydomain.com/CRMService.svc/");
                    CRMServiceReference.CRMEntities db = new CRMServiceReference.CRMEntities(uri);
                    var data = from l in db.Lists select l;

    As soon as I try to do anything with the data it flips out, as basically it has not been able to access the service at all.

    Can anyone give me any pointers here at all? I am at the end of my tether with this. None of the tutorials I've seen seem to take into account how to host on a domain situation. 

    By the way, I've checked with my Domain/Hosting provider and they don't seem to think that I would need to specify a port on this, but I don't know if this is the case.

    Hoping... really really hoping anyone can help.

    Thanks


    Wednesday, March 21, 2012 9:19 AM

Answers

  • Finally solved this, which was just as well as no one seemed to have any idea whatsoever.

    What I did was:

    Removed the MYSQL .Net connector that I had been using and installed the latest version which is in my case 6.5.4.0

    This will obviously require you to change all MySQL references in your config file to match this version. Due to the fact that I am sick to the back teeth of tutorials that assume you know things like these and so don't mention this to you, I will illustrate.

    Below is the before

    <profile defaultProvider="MySQLProfileProvider">
          <providers>
            <add name="DefaultProfileProvider" type="System.Web.Providers.DefaultProfileProvider, System.Web.Providers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" connectionStringName="DefaultConnection" applicationName="/" />
            <remove name="MySQLProfileProvider" />
            <add name="MySQLProfileProvider" type="MySql.Web.Profile.MySQLProfileProvider, MySql.Web, Version=6.4.4.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d" applicationName="Security" description="Profiles" connectionStringName="LocalMySqlServer" writeExceptionsToEventLog="False" autogenerateschema="False" />
          </providers>
        </profile>

    Below is the after

    <profile defaultProvider="MySQLProfileProvider">
          <providers>
            <add name="DefaultProfileProvider" type="System.Web.Providers.DefaultProfileProvider, System.Web.Providers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" connectionStringName="DefaultConnection" applicationName="/" />
            <remove name="MySQLProfileProvider" />
            <add name="MySQLProfileProvider" type="MySql.Web.Profile.MySQLProfileProvider, MySql.Web, Version=6.4.5.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d" applicationName="Security" description="Profiles" connectionStringName="LocalMySqlServer" writeExceptionsToEventLog="False" autogenerateschema="False" />
          </providers>
        </profile>

    Notice that the Line headed <add name="MySQLProfileProvider" has the new Version type Version=6.4.5.0 whereas it was previously Version 6.4.4.0

    I added the following MySQL references:

    MySql.Data
    MySql.Data.Entity
    MySql.Web

    Ensuring that (again, in detail just in case) you then click on the reference in the solution pane and make sure that you have the Copy Local element set to true

    I then added the following element to my Web.config file

      <system.data>
        <DbProviderFactories>
          <add name="MySQL Data Provider" invariant="MySql.Data.MySqlClient" description=".Net Framework Data Provider for MySQL" type="MySql.Data.MySqlClient.MySqlClientFactory, MySql.Data, Version=6.5.4.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d" />
        </DbProviderFactories>
      </system.data>

    This I added under the Configuration node and immediately under the ConnectionStrings. I don't know if it's that important exactly where it is situated in the Config file but this worked for me.

    Now, I'm not sure if adding a port is absolutely necessary, but on talking to my hosting company they seemed to think that I wouldn't need to set up a port and I haven't. I can browse straight to the service via the subdomain url as shown below.

    http://services.mydomain.com/MyService.svc

    this works for me. I only point this out as almost every single tutorial I have seen always show you using localhost, I think I've only seen one or two that use an actual domain situation, for a good long while this led me to believe that you could only set this up if you have direct access to IIS configuration which I don't.

    I completely understand why you would need/want to set a port, but, as I have no access to the IIS settings and limited access to the actual host server settings, I don't know how I would achieve setting a port. In my case the service is accessible without a port specification.

    Anyway, the service is now working. So hopefully this will be of use to someone else.

    I would like to give a plea to all those kind experts out there who do do these fantastic tutorials. Not all of us have computer science degrees, some of us fell into this industry just through a genuine interest. Thanks to you kind experts, we've been able to make ourselves a living doing this stuff and actually teach ourselves through your help. My plea, however, is that you add just a little more context into your tutorials. I.e. it would be nice to show http://localhost right next to http://mydomain. Also, when you say add a piece of code somewhere, it would be nice if you could occasionally tell us exactly whereabouts to add it etc. This isn't a complaint as such, just a plea to make it a bit easier on those of us without the formal computer education.

    Thank you one and all


    • Marked as answer by Darkly Friday, March 23, 2012 10:32 AM
    Friday, March 23, 2012 10:32 AM

All replies

  • Okay, so I'm assuming that no one has any idea with this. After doing much digging I've had some progress but am still stuck.

    What I did was this. Placed the 

    [System.ServiceModel.ServiceBehavior(IncludeExceptionDetailInFaults = true)]

    attribute above my Service class and this kind of indicated that the service appeared to be trying to access some files or config settings locally on my laptop. After a bit of fiddling, I trashed the original service and re-built it but this time setting the Asp Membership config settings that I'd neglected to do previously.

    I then added the Entity model. Set the permissions again and with the above attribute still on, loaded the service again. This time, when I tried to input the Url  to access the service, I received the following error.

    The exception message is 'The specified store provider cannot be found in the configuration, or is not valid.'. See server logs for more details. The exception stack trace is:

    at System.Data.EntityClient.EntityConnection.GetFactory(String providerString) at System.Data.EntityClient.EntityConnection.ChangeConnectionString(String newConnectionString) at System.Data.EntityClient.EntityConnection..ctor(String connectionString) at System.Data.Objects.ObjectContext.CreateEntityConnection(String connectionString) at System.Data.Objects.ObjectContext..ctor(String connectionString, String defaultContainerName) at RotaSolutions.WCF.Models.rotasolu_crmEntities..ctor() in C:\Users\Paul\Dropbox\Projects\WCF\RotaSolutions.WCF\RotaSolutions.WCF\Models\CRMModel.Designer.cs:line 34 at invoke_constructor() at System.Data.Services.DataService`1.CreateDataSource() at System.Data.Services.DataService`1.CreateDataSourceInstance() at System.Data.Services.DataService`1.CreateProvider() at System.Data.Services.DataService`1.HandleRequest() at System.Data.Services.DataService`1.ProcessRequestForMessage(Stream messageBody) at SyncInvokeProcessRequestForMessage(Object , Object[] , Object[] ) at System.ServiceModel.Dispatcher.SyncMethodInvoker.Invoke(Object instance, Object[] inputs, Object[]& outputs) at System.ServiceModel.Dispatcher.DispatchOperationRuntime.InvokeBegin(MessageRpc& rpc) at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage5(MessageRpc& rpc) at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage41(MessageRpc& rpc) at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage4(MessageRpc& rpc) at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage31(MessageRpc& rpc) at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage3(MessageRpc& rpc) at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage2(MessageRpc& rpc) at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage11(MessageRpc& rpc) at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage1(MessageRpc& rpc) at System.ServiceModel.Dispatcher.MessageRpc.Process(Boolean isOperationContextSet)

    Once again, if anyone can give me any pointers, I'd be extremely grateful. This is at least a hell of a lot more verbose than the errors I'd been receiving previously.

    Thursday, March 22, 2012 5:01 PM
  • Finally solved this, which was just as well as no one seemed to have any idea whatsoever.

    What I did was:

    Removed the MYSQL .Net connector that I had been using and installed the latest version which is in my case 6.5.4.0

    This will obviously require you to change all MySQL references in your config file to match this version. Due to the fact that I am sick to the back teeth of tutorials that assume you know things like these and so don't mention this to you, I will illustrate.

    Below is the before

    <profile defaultProvider="MySQLProfileProvider">
          <providers>
            <add name="DefaultProfileProvider" type="System.Web.Providers.DefaultProfileProvider, System.Web.Providers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" connectionStringName="DefaultConnection" applicationName="/" />
            <remove name="MySQLProfileProvider" />
            <add name="MySQLProfileProvider" type="MySql.Web.Profile.MySQLProfileProvider, MySql.Web, Version=6.4.4.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d" applicationName="Security" description="Profiles" connectionStringName="LocalMySqlServer" writeExceptionsToEventLog="False" autogenerateschema="False" />
          </providers>
        </profile>

    Below is the after

    <profile defaultProvider="MySQLProfileProvider">
          <providers>
            <add name="DefaultProfileProvider" type="System.Web.Providers.DefaultProfileProvider, System.Web.Providers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" connectionStringName="DefaultConnection" applicationName="/" />
            <remove name="MySQLProfileProvider" />
            <add name="MySQLProfileProvider" type="MySql.Web.Profile.MySQLProfileProvider, MySql.Web, Version=6.4.5.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d" applicationName="Security" description="Profiles" connectionStringName="LocalMySqlServer" writeExceptionsToEventLog="False" autogenerateschema="False" />
          </providers>
        </profile>

    Notice that the Line headed <add name="MySQLProfileProvider" has the new Version type Version=6.4.5.0 whereas it was previously Version 6.4.4.0

    I added the following MySQL references:

    MySql.Data
    MySql.Data.Entity
    MySql.Web

    Ensuring that (again, in detail just in case) you then click on the reference in the solution pane and make sure that you have the Copy Local element set to true

    I then added the following element to my Web.config file

      <system.data>
        <DbProviderFactories>
          <add name="MySQL Data Provider" invariant="MySql.Data.MySqlClient" description=".Net Framework Data Provider for MySQL" type="MySql.Data.MySqlClient.MySqlClientFactory, MySql.Data, Version=6.5.4.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d" />
        </DbProviderFactories>
      </system.data>

    This I added under the Configuration node and immediately under the ConnectionStrings. I don't know if it's that important exactly where it is situated in the Config file but this worked for me.

    Now, I'm not sure if adding a port is absolutely necessary, but on talking to my hosting company they seemed to think that I wouldn't need to set up a port and I haven't. I can browse straight to the service via the subdomain url as shown below.

    http://services.mydomain.com/MyService.svc

    this works for me. I only point this out as almost every single tutorial I have seen always show you using localhost, I think I've only seen one or two that use an actual domain situation, for a good long while this led me to believe that you could only set this up if you have direct access to IIS configuration which I don't.

    I completely understand why you would need/want to set a port, but, as I have no access to the IIS settings and limited access to the actual host server settings, I don't know how I would achieve setting a port. In my case the service is accessible without a port specification.

    Anyway, the service is now working. So hopefully this will be of use to someone else.

    I would like to give a plea to all those kind experts out there who do do these fantastic tutorials. Not all of us have computer science degrees, some of us fell into this industry just through a genuine interest. Thanks to you kind experts, we've been able to make ourselves a living doing this stuff and actually teach ourselves through your help. My plea, however, is that you add just a little more context into your tutorials. I.e. it would be nice to show http://localhost right next to http://mydomain. Also, when you say add a piece of code somewhere, it would be nice if you could occasionally tell us exactly whereabouts to add it etc. This isn't a complaint as such, just a plea to make it a bit easier on those of us without the formal computer education.

    Thank you one and all


    • Marked as answer by Darkly Friday, March 23, 2012 10:32 AM
    Friday, March 23, 2012 10:32 AM