Member Avatar for micmo

Hi Guys,

I'm currently developing a project using WCF (hosted on local IIS) which connects to a local SQL database using LINQ to get data.

My problem is that when I run the code, 9/10 times it'll fail with the "Specified Cast Is Not Valid" error, but the other 1/10 times it will return the correct value (a messagebox with the records 'name' field.

The code snippets below are from my wcf datacontract/servicecontract, server and client code. There is only one record in the table im retrieving.

WCF Service (IFaveoService.cs)

[ServiceContract]
    [ServiceKnownType(typeof(SRType))]
    public interface IFaveoService
    {
        [OperationContract]
        IEnumerable<SRType> GetSRTypeByID(int srID);

    }

    [DataContract]
    [Database]
    public class FaveoData : DataContext
    {
        public Table<SRType> SRTypes;

        public FaveoData(string connStr)
            : base(connStr)
        {
        }
    }

    [DataContract]
    [Table(Name = "SRTYPES")]
    public class SRType
    {
        [DataMember]
        [Column(IsPrimaryKey=true, IsDbGenerated=true)]
        public int srTypeID
        {
            get;
            set;
        }

        [DataMember]
        [Column]
        public string srName
        {
            get; 
            set;
        }
    }

Server (FaveoService.cs)

class FaveoService : IFaveoService
    {
        

        public IEnumerable<SRType> GetSRTypeByID(int srID)
        {

            string userInfo = "User Id=xx;Password=xx;Trusted_Connection=False";
            string connStr = @"Server=.\SQLExpress;Server=xx;Database=FaveoData;"+userInfo;

            FaveoData db = new FaveoData(connStr);

            //select the record where srTypeID==1 from SRTYPES table in db
            IEnumerable<SRType> types = from t in db.SRTypes where t.srTypeID == 1 select t;
            
            return types;
        }

    }

Client (Program.cs)

client = new FaveoServiceClient();
            client.Open();

            try
            {
                FaveoServices.SRType[] sr = client.GetSRTypeByID(1);
                
                foreach(FaveoServices.SRType t in sr)
                {
                    MessageBox.Show(t.srName.ToString());  
                }
            }
            catch (Exception e)
            {
                MessageBox.Show(e.ToString());

            }
            client.Close();

Web.Config

<?xml version="1.0"?>
<configuration>
  
  <system.diagnostics>
    <sources>
      <source name="System.ServiceModel.MessageLogging" switchValue="Warning, ActivityTracing">
        <listeners>
          <add type="System.Diagnostics.DefaultTraceListener" name="Default">
            <filter type="" />
          </add>
          <add name="ServiceModelMessageLoggingListener">
            <filter type="" />
          </add>
        </listeners>
      </source>
      <source name="System.ServiceModel" switchValue="Verbose,ActivityTracing"
        propagateActivity="true">
        <listeners>
          <add type="System.Diagnostics.DefaultTraceListener" name="Default">
            <filter type="" />
          </add>
          <add name="ServiceModelTraceListener">
            <filter type="" />
          </add>
        </listeners>
      </source>
    </sources>
    <sharedListeners>
      <add initializeData="c:\inetpub\wwwroot\faveoservice\web_messages.svclog"
        type="System.Diagnostics.XmlWriterTraceListener, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
        name="ServiceModelMessageLoggingListener" traceOutputOptions="Timestamp">
        <filter type="" />
      </add>
      <add initializeData="c:\inetpub\wwwroot\faveoservice\web_tracelog.svclog"
        type="System.Diagnostics.XmlWriterTraceListener, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
        name="ServiceModelTraceListener" traceOutputOptions="Timestamp">
        <filter type="" />
      </add>
    </sharedListeners>
    <trace autoflush="true" />
  </system.diagnostics>
  <system.web>
    <compilation debug="true" targetFramework="4.0" />
    <httpRuntime maxRequestLength="32768"/>
  </system.web>
  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true"/>
  </system.webServer>
  <system.serviceModel>
    <diagnostics>
      <messageLogging logMalformedMessages="true" logMessagesAtServiceLevel="true"
        logMessagesAtTransportLevel="true" />
    </diagnostics>
    <bindings>
      <netTcpBinding>
        <binding sendTimeout="00:03:00" receiveTimeout="00:03:00" />
      </netTcpBinding>
    </bindings>
    <behaviors>
      <serviceBehaviors>
        <behavior name="MyServiceTypeBehaviors">
          <serviceMetadata httpGetEnabled="true" />
          <serviceDebug includeExceptionDetailInFaults="true" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <services>
      <service behaviorConfiguration="MyServiceTypeBehaviors" name="FaveoServices.FaveoService">
        <endpoint address="" binding="wsHttpBinding" contract="FaveoServices.IFaveoService" />
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
        <host>
          <baseAddresses>
            <add baseAddress="http://localhost/FaveoService" />
          </baseAddresses>
          <timeouts closeTimeout="00:03:00" openTimeout="00:03:00" />
        </host>
      </service>
    </services>
  </system.serviceModel>
 </configuration>

When debugging the server code, FaveoService.cs, I get the "Specified cast not valid" in the local variable types->Results View->base, but then the exception clientside says:

"An error occurred while receiving the HTTP response to [url]http://mmorris-pc2/FaveoService/FaveoService.svc[/url]. This could be due to the service endpoint binding not using the HTTP protocol. This could also be due to an HTTP request context being aborted by the server (possibly due to the service shutting down). See server logs for more details."
InnerException	{"The underlying connection was closed: An unexpected error occurred on a receive."}	System.Exception {System.Net.WebException}
InnerException	{"Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host."}	System.Exception {System.IO.IOException}

(theres nothing in the event logs & no wcf logs were created!)

As mentioned before ... sometimes it works ... but most of the time it doesnt. I'm not sure what was different for it to work that one time :(

Any ideas? From what I can see all of my types are the same?!

Thanks,
Michael

Can you point me to the row where is comes to the error?
Its hard to look in such a code, which has so many custom objects - it will take a lot of time to figure out what all you have there.
thx
Mitja

Member Avatar for micmo

ok, so when debugging I debug both FaveoService.cs (the server code) and Program.cs (the client app).

It starts off in Program.cs line 6 which takes us to FaveoService.cs, line 14. When I look at the debug information for local variable 'types' (line 16), I can see the error message "Specified cast not valid" as part of the "Results View" information of the object 'types' (which should be IEnumerable<SRType>).

Once I have returned 'types' from FaveoService.cs, it fails with an exception so jumps to the catch statement on line 13 of Program.cs and subsiquently shows the messagebox with the message "An error occurred while receiving the HTTP response ....".

The thing I dont get is that in my DataContract I have specified the columns correctly to match 100% the database, and the OperationContract is of the same type (IEnumerable<SRType>) as the method i've implimented. So I'm not sure why the returned value from the db (FaveoService.cs line 14) is complaining about type casting.

Member Avatar for micmo

(btw, the database has a table "SRTYPES" with columns srTypeID (int, primary key, IDENTITY) and srName (varchar(20)), with only one record: srTypeID=1, srName="test".

The thing that really gets me is why it worked once, but then not the next time I ran it (without changing any code)!

Member Avatar for micmo

hmmm, I've just found something really interesting!!
If I just run the VS Project, it fails with the exception mentioned before, but if I drill down into the local variables in FAveoService.cs it works?!?! See the attached screenshot.

the variable 'db' is my DataContext object with 'SRTypes' being the DataContract linked to my table, and 'types' is the IEnumerable<SRTypes> being returned from the method. In the Results View of db you can see the error message which is causing all of the problems, but in types Result View it is returning the correct object!!!

So it seems that if I drill into db first, and then types, it returns correctly and the client works fine with no exceptions.

Do you think it's the expanding of the local variable in the debug window which will "enumerate the IENumerable" that fixes my issue? If so - what am I doing wrong in my code?!

Line 16 of FaveoService.cs says you are returning an IEnumerable<SRType> but your receiving end, line 6 of Program.cs is trying to put it into an FaveoServices.SRType[], not the same type at all.

The reason it appears to work in the debugger is you are looking at what happens when you enumerate through the result. It even says that in your screenshot.

Try changing the type in Line 6 of Program to IEnumberable<SRType>. That should be the only thing you need to change.

Member Avatar for micmo

I tried that too

IEnumerable<FaveoServices.SRType> sr = client.GetSRTypeByID(1);

but it still fails when I just run the code.

I have however managed to consistantly run the program so it works .... but only when debugging.
When the debugger has reached the "return types;" line (FaveoService.cs L16) if I do the following, the program works:
-in the locals window drill down into db->SRTypes->Results View (shows the casting error)
-then in the locals window drill down to types->Results View
This then shows (under Results View) FaveoServices.SRType - which is the object that needs to be returned.
(exactly the same as the screenshot in my last post)

If I DON'T drill down into db and then types, the program fails on the client side.

So, why does the db.SRTypes class need to be enumerated before I can return the value? Is there something I need to do in the code?

You can force it to enumerate all the values by calling ToList on the enumerator and return the resulting list instead.

Member Avatar for micmo

so like:
server:

FaveoData db = new FaveoData(connStr);
IEnumerable<SRType> types = from t in db.SRTypes where t.srTypeID == 1 select t;
return types.ToList();

client:

IEnumerable<FaveoServices.SRType> sr = client.GetSRTypeByID(1);

because using the above I now get the "Specified cast not valid" exception on the client (screenshot below).
Yet, once again, if I enumerate the db.SRTypes via the debugger (screenshot as before) and then continue with the debugging, I don't get any errors!
So I don't think it's the returning that the problem, but the IEnumerator<SRType> as it can't do that bit. Do you get what I mean?

Client side would be List<SRType> as the type instead of IEnumerable<SRType>.

Looks like I might have to read up on WCF sometime :)

Member Avatar for micmo

Solved!!

client:

FaveoServices.SRType[] sr = (FaveoServices.SRType[]) client.GetSRTypes();
foreach (FaveoServices.SRType s in sr)
{
MessageBox.Show(s.srName.ToString());
}

server:

public List<SRType> GetSRTypes()
{
FaveoData db = new FaveoData(connStr);
IEnumerable<SRType> types = from t in db.SRTypes select t;
return types.ToList();
}

wcf service:

[OperationContract]
List<SRType> GetSRTypes();

...

[DataMember]
[Column(IsPrimaryKey = true, IsDbGenerated = true, Storage = "_ID", DbType = "Int NOT NULL IDENTITY")]
public int srTypeID
{
get { return _ID; }
set { _ID = value; }
}

[DataMember]
[Column(Storage = "_name", DbType = "VarChar(20) NOT NULL", CanBeNull = false)]
public string srName
{
get { return _name; }
set { _name = value;  }
}

The reason I was getting the cast errors was because in the data contract I needed to be more specific with the DataMember column attributes (adding the DbType and CanBeNull attributes).
I got the correct values by using SQLMETA to produce auto-generated code, and then just used that :)

WIN!!

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.