0

I created a WCF service in Visual Studio, and as said in the title, it can't access a SQL Server database whilst a console project, built with more or less the same code, can.

Here is the IService interface:

[ServiceContract]
public interface IService
{
    [OperationContract]
    Supermarche getSupermarche();
}

Here is the implementation of the method:

public class Service : IService
{
    public Supermarche getSupermarche()
    {
        //récupération en base
        Model.Supermarche supermarche = null;

        using (var ctx2 = new MarketContext("sqlserverPersonalId"))
        {
            supermarche = ctx2.Supermarches.First<Model.Supermarche>();
        }

        return supermarche;

        //return new Supermarche() { SupermarcheId = 5, Magasins = null };
    }
}

With the last return statement, the app ClientTestWCF is able to invoke the getSupermarche() method and it gets the correct result. Then I guess the problem comes from the database access.

This database is used with Entity Framework; as there seems to be no problem with that (as the last return above works) I won't show it here. Please just notice that I adorned the classes with [DataContract] and [DataMember].

The service is published in IIS, those of Windows and not the integrated one.

Here is the Web.config file (in the Service project):

<?xml version="1.0" encoding="utf-8"?>
<configuration>
    <configSections>
        <section name="entityFramework"
                 type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
                requirePermission="false"/>
    </configSections>

    <appSettings>
        <add key="aspnet:UseTaskFriendlySynchronizationContext" value="true"/>
    </appSettings>
    <system.web>
        <compilation debug="false" targetFramework="4.7.2"/>
        <httpRuntime targetFramework="4.7.2"/>
    </system.web>
    <system.serviceModel>
        <behaviors>
            <serviceBehaviors>
                <behavior>
                    <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
                    <serviceDebug includeExceptionDetailInFaults="true"/>
                </behavior>
            </serviceBehaviors>
        </behaviors>
        <services>
            <service name="Service">
                <endpoint address="" 
                          binding="basicHttpBinding" 
                          contract="IService"/>
                <host>
                    <baseAddresses>
                        <add baseAddress="http://localhost:8080"/>
                    </baseAddresses>
                </host>
            </service> 
        </services>
        <protocolMapping>
            <add binding="basicHttpBinding" scheme="http"/>
        </protocolMapping>    
        <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true"/>
    </system.serviceModel>
    <system.webServer>
        <modules runAllManagedModulesForAllRequests="true"/>
            <directoryBrowse enabled="true"/>
            <handlers>
                <add name="serviceHandler" verb="*" path=".svc"
                     type="System.ServiceModel.Activation.HttpHandler, System.ServiceModel, Version=3.0.0.0, Culture=neutral,PublicKeyToken=31bf3856ad364e35"/>
            </handlers>
      </system.webServer>
      <entityFramework>
          <providers>
              <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer"/>
          </providers>
      </entityFramework>
      <connectionStrings>
          <add name="sqlserver" 
               connectionString="Data Source=xxx\SQLEXPRESS;Integrated Security=True;Connect Timeout=90;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False;Initial Catalog=Market" 
               providerName="System.Data.SqlClient"/>
          <add name="sqlserverPersonalId" 
               connectionString="Data Source=xxx\SQLEXPRESS;Initial Catalog=Market;User ID=xxx;Password=xxx;Connect Timeout=90;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False" 
               providerName="System.Data.SqlClient"/>
      </connectionStrings>
</configuration>

EDIT:

I forgot the error, got in the client Microsoft test app:

Échec de l'appel du service. Causes possibles : le service est peut être hors ligne ou inaccessible ; la configuration côté client ne correspond pas au proxy ; le proxy existant n'est pas valide. Reportez-vous à la trace de la pile pour plus de détails. Vous pouvez tenter une récupération en démarrant un nouveau proxy, en restaurant la configuration par défaut ou en actualisant le service.

it means:

Service call failed.the service can be unreachable, the existing proxy is not valid.You can try to create a new proxy, by restoring the default configuration or by updating the service.

Here is the stack trace:

Une erreur s'est produite lors de la réception de la réponse HTTP à http://localhost/market8/Service.svc. La raison peut en être que la liaison de point de terminaison de service n'utilise pas le protocole HTTP. Cela peut également être dû au fait qu'un contexte de requête HTTP a été ignoré par le serveur (peut-être à cause de l'arrêt du service). Pour plus d'informations, consultez les journaux du serveur.

it means:

There was an error at the http answer reception for the http://localhost/market8/Service.svc call, the endpoint may not use the HTTP protocol, or the HTTP request context may be ignored by the server (cause : service stopped?).

Server stack trace: à System.ServiceModel.Channels.HttpChannelUtilities.ProcessGetResponseWebException(WebException webException, HttpWebRequest request, HttpAbortReason abortReason)
à System.ServiceModel.Channels.HttpChannelFactory`1.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout) à System.ServiceModel.Channels.RequestChannel.Request(Message message, TimeSpan timeout) à System.ServiceModel.Dispatcher.RequestChannelBinder.Request(Message message, TimeSpan timeout) à System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout) à System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation) à System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)

Exception rethrown at [0]: à System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg) à System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type) à IService.getSupermarche() à ServiceClient.getSupermarche()

Inner Exception: La connexion sous-jacente a été fermée : Une erreur inattendue s'est produite lors de la réception. à (it means : the underlying connection was closed : an unexpected error happened at the reception)

System.Net.HttpWebRequest.GetResponse() à System.ServiceModel.Channels.HttpChannelFactory`1.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout)

Inner Exception: Impossible de lire les données de la connexion de transport : Une connexion existante a dû être fermée par l’hôte distant.
(it means : no way to read the datas of the transport connection : a existing connection had to be closed)

à System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 size) à System.Net.PooledStream.Read(Byte[] buffer, Int32 offset, Int32 size) à System.Net.Connection.SyncRead(HttpWebRequest request, Boolean userRetrievedStream, Boolean probeRead)

Inner Exception: Une connexion existante a dû être fermée par l’hôte distant
(it means : a remote connection had to be closed by the remote host) à System.Net.Sockets.Socket.Receive(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags) à System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 size)

The service is deployed to IIS.

EDIT Here is the code for the main() method in the console project:

static void Main(string[] args)
        {
            using (var ctx = new MarketContext("sqlserver"))
            {
                new MyDataInitializer().InitializeDatabase(ctx);

                //var produitMagasin = new ProduitMagasin() { Nom = "Pommes", Quantite = 10 };
                //ctx.ProduitsMagasin.Add(produitMagasin);

                //var rayon1 = new Rayon() { Nom = "Fruits & Légumes", Produits = new List<ProduitMagasin> { produitMagasin } };
                //ctx.Rayons.Add(rayon1);

                var produitMagasin1 = new ProduitMagasin() { Nom = "Pommes", Quantite = 10 };
                var produitMagasin2 = new ProduitMagasin() { Nom = "Poires", Quantite = 5 };
                var rayon1 = new Rayon() { Nom = "fruits & légumes", Produits = new List<ProduitMagasin>() { produitMagasin1, produitMagasin2 } };
                var magasin1 = new Magasin() { Rayons = new List<Rayon>() { rayon1 } };
                var supermarche1 = new Supermarche() { Magasins = new List<Magasin> { magasin1 } };
                ctx.Supermarches.Add(supermarche1);

                ctx.SaveChanges();

                Console.WriteLine("Programme exécuté");
                Console.ReadLine();

           }
        }

I use "sqlserver" as the connectionString, so I changed the service connection string to "sqlserver" too but it didn't help.

EDIT It is worth noticing that when the getSupermarche() method returns an artificial Supermarche object, there is no error and I can get the expected result. So the problem seems to come from the database access, not from the http configuration (unless both are linked but I don't think so).

Linq problem? Here are the references in the console project: console project's references and here are the references of the service project: service project's references

I didn't noticed a problem thought.

lolveley
  • 1,659
  • 2
  • 18
  • 34
  • 1
    So when it tries to connect, what error do you get? Can you see the connection attempt(s) in SQL Server's logs? If so, what errors do they say? – Thom A Jan 20 '20 at 11:07
  • Unfortunately the errors aren't in English; Stack Overflow is an English community (I see you have translated part of one, but not the rest). – Thom A Jan 20 '20 at 11:13
  • You say your working application has "more or less" the same code, but we can't assess that as you haven't shown it. Also, does the working application connect to the same database? Also, what have you tried? Enable WCF Tracing to see the actual exception. Chances are that, because you're using Entity Framework entities as DTOs (you shouldn't), you have a circular reference so your entity can't be properly serialized, or because of lazy loading you're getting a "context disposed" exception. There is not enough information in this question to troubleshoot this issue; research it yourself. – CodeCaster Jan 20 '20 at 11:14
  • Seems that you do not have service configured properly because of `there was an error at the http answer reception for the http://localhost/market8/Service.svc call` please check service configuration and Url. Here [is the documentation](https://learn.microsoft.com/en-us/dotnet/framework/wcf/feature-details/how-to-host-a-wcf-service-in-iis). You can check web service Url using web browser. – oleksa Jan 20 '20 at 11:27
  • I translated the remaining french text, and I suggested the error could come from the database access, in my edit of the question. – lolveley Jan 20 '20 at 12:30
  • when I try to connect to the database with a windows identification, the service try to use an user id beginning with "WORKGROUP", and it is rejected by SQL Server. And when I try to use SQL server authentication, ... I see nothing in SQL server ' s log. – lolveley Jan 20 '20 at 15:59

1 Answers1

0

solved!

in fact, with the help of the visual debugger and the local run of the service(using WCFTestClient.exe app), I saw that the call to the context , namely

        using (var ctx2 = new MarketContext("sqlserver"))
        {
            var sm = ctx2.Supermarches.First();

            return sm;
        }

produces a sm variable of type : System.Data.DynamicProxies.Supermarche_xxx, and I guess it make the service crash. then I searched and found it: Why is EF returning a proxy class instead of the actual entity?, and then added

ctx2.Configuration.ProxyCreationEnabled = false;

before pulling the datas, and it worked.

lolveley
  • 1,659
  • 2
  • 18
  • 34