toList() System.InvalidCastException was unhandled by user code - wcf

I have written a WCF service using LINQ to SQL (using the following article at codeporject). I am facing the invalid cast exception when i invoke the .ToList() method of an object after i have already made a wcf function call of the same service against the same database.
The exception is:
System.InvalidCastException was unhandled by user code
Message=Specified cast is not valid.
Source=System.Data
StackTrace:
at System.Data.SqlClient.SqlBuffer.get_Int64()
at System.Data.SqlClient.SqlDataReader.GetInt64(Int32 i)
at Read_Command(ObjectMaterializer`1 )
at System.Data.Linq.SqlClient.ObjectReaderCompiler.ObjectReader`2.MoveNext()
at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
at SystemsManager.ACS.GetCommands(Int64 agentId) in E:\Projects\SystemsManager\AgentControlService\ACS.svc.cs:line 167
at SyncInvokeGetCommands(Object , Object[] , Object[] )
at System.ServiceModel.Dispatcher.SyncMethodInvoker.Invoke(Object instance, Object[] inputs, Object[]& outputs)
at System.ServiceModel.Dispatcher.DispatchOperationRuntime.InvokeBegin(MessageRpc& rpc)
InnerException:
The specific line i am having issue is with the ToList() method
public List<Command> GetCommands(long agentId)
{
var cmd = from command in db.Command where (command.AgentId == agentId) select command;
return cmd.ToList();
}
When debugging, the return statment throws exception. When view the value of cmd.ToList() in Quick Watch of VS 2010, the exception is shown.
Now the strangest thing is: Pressing "Re-Evaluate" button a couple of times changes the exception to required object list in Quick watch. Infact i have to press "Re-evaluate" at least three times.
I have generated client using svcutil tool after my most recent changes to the service/database.
I am calling the method using the following code from a windows service:
var agent = client.GetAgentByIpAddress(myIPAddress);
client.Close();
if (agent != null)
{
if (agent.AgentId != -1)
{
client = new ACSClient();
var command = client.GetCommands(agent.AgentId);
.....
Here is the model of Command in the interface of the wcf service.
[DataContract]
[Table(Name = "Command")]
public class Command
{
[DataMember, Column(IsPrimaryKey = true, Name = "Command_Id", AutoSync = AutoSync.OnInsert, IsDbGenerated = true, DbType = "Bigint NOT null identity")]
public long CommandId { get; set; }
[DataMember, Column(Name = "Agent_Id")]
public long AgentId { get; set; }
[DataMember, Column(Name = "Name")]
public string CommandName { get; set; }
[DataMember, Column(Name = "Paramters")]
public string CommandParamters { get; set; }
[DataMember, Column(Name = "Is_Fetched")]
public bool IsFectched { get; set; }
[DataMember, Column(Name = "Status")]
public long Status { get; set; }
[DataMember, Column(Name = "Response")]
public string Response { get; set; }
[DataMember, Column(Name = "Created")]
public DateTime Created { get; set; }
[DataMember, Column(Name = "Last_Modified")]
public DateTime LastModified { get; set; }
[DataMember, Column(Name = "Is_Enabled")]
public bool IsEnabled { get; set; }
}
Important thing is: My database file is located in AppData folder of the WCF service. I am using only one instance of db object (refer to 1st code block above) throughout my wcf service and i am wondering if this could be cause of the problem???
Also, i have called a couple of similar method of this very same wcf service from a desktop application but i have not faced any such issue.
Please help. if more details are needed, please state so.. The only thing that can come to mind is that perhaps the database is in use and when another connection is made to the database by the service, it fails. and retrying it a couple of times using the Quick Watch > Re-evaluate button displays the required values in the watch window without throwing any error.
Kindly help on this one. Quick responses are highly appreciated.
Thanks.
Steve

Never mind guys. I solved it.
For anyone else who is getting invalid cast exception, here is the solution.
The error only occurs when actual class model is different that the database.
If you have created the class model by hand coding it, the you must match each column name of the table to your corresponding class. LINQ to sql encounters error when it cannot convert a database type to .Net type and throws invalid cast exception.
So in most cases, either fixing the error manually in the model class or regenerating the class will solve the problem.

Related

How can I deserializing JSON while returns different type?

I post some data to the remote server. When the data run succeeded, it returns:
{"access_token":"sd234sd234sdf324","expires_in":7200}
When it failed, it returns:
{"errcode":40013,"errmsg":"invalid appid"}
Here is my code:
HttpClient HC = new HttpClient();
HttpResponseMessage HRM = await HC.PostAsync("https://www.microsoft/callback/aaa/), null);
string Content = await HRM.Content.ReadAsStringAsync();
Models.SuccessModel SM=(Models.SuccessModel)JsonSerializer.Deserialize(Content, typeof(Models.SuccessModel));
The last part for converting JSON to the class, I used the SuccessModel yet but if returns the failed JSON it will throw an error which Type is wrong.
I know what the error is. But how can I deal with this?
I want to get whether it is succeeded or failed and get the value of it.
Thank you.
Make another model for error as follows:
public class ErrorModel
{
public string errcode {get;set;}
public string errmsg {get;set;}
}
Then do as follows:
string response = await HRM.Content.ReadAsStringAsync();
if (response.Contains("access_token", StringComparison.OrdinalIgnoreCase))
{
Models.SuccessModel successModel =(Models.SuccessModel)JsonSerializer.Deserialize(response, typeof(Models.SuccessModel));
} else
{
ErrorModel erroModel = (Models.ErrorModel)JsonSerializer.Deserialize(response,typeof(Models.ErrorModel));
}
However, you can work this way
public class Model
{
public string access_token { get; set;}
public long expires_in { get; set;}
public int errcode { get; set;}
public string errmsg { get; set;}
}
So just get the response and check errcode when use it, no need to check when Deserialize

The 0.3 WebJobs SDK broke my parameter bindings

I have the following method definition:
public static void ProcessPackageRequestMessage(
[QueueTrigger(queues.PACKAGE)] PackageRequestMessage message,
[Blob(blobs.PACKAGE + "/{RequestId}_{BlobFile}")] ICloudBlob blob,
[Table(tables.PACKAGE)] CloudTable table,
[Queue(queues.EMAIL)] out PackageEmailMessage packageEmailMessage)
The class PackageRequestMessage is defined as follows:
public class PackageRequestMessage
{
public Guid RequestId { get; set; }
public Guid FactoryId { get; set; }
public string BlobFile { get; set; }
public string SKU { get; set; }
public string EmailAddress { get; set; }
}
In version 0.2 of the SDK, when a JSON message of PackageRequestMessage was posted to the queue, this method was called, and the appropriate Blob was found, based on the parameters in the PackageRequestMessage (RequestId, and BlobFile), and all worked well.
Now, in version 0.3 of the SDK, I get the following error:
System.InvalidOperationException: System.InvalidOperationException: Exception binding parameter 'blob' ---> System.InvalidOperationException: No value for name parameter 'RequestId'
at Microsoft.Azure.Jobs.RouteParser.ApplyNamesWorker(String pattern, IDictionary2 names, Boolean allowUnbound)
at Microsoft.Azure.Jobs.RouteParser.ApplyBindingData(String pattern, IReadOnlyDictionary2 bindingData)
at Microsoft.Azure.Jobs.Host.Blobs.Bindings.BlobBinding.Bind(BindingContext context)
at Microsoft.Azure.Jobs.Host.Runners.TriggerParametersProvider1.Bind()
--- End of inner exception stack trace ---
at Microsoft.Azure.Jobs.Host.Runners.DelayedException.Throw()
at Microsoft.Azure.Jobs.Host.Runners.WebSitesExecuteFunction.ExecuteWithSelfWatch(MethodInfo method, ParameterInfo[] parameterInfos, IReadOnlyDictionary2 parameters, TextWriter consoleOutput)
at Microsoft.Azure.Jobs.Host.Runners.WebSitesExecuteFunction.ExecuteWithOutputLogs(FunctionInvokeRequest request, IReadOnlyDictionary2 parameters, TextWriter consoleOutput, CloudBlobDescriptor parameterLogger, IDictionary2 parameterLogCollector)
at Microsoft.Azure.Jobs.Host.Runners.WebSitesExecuteFunction.ExecuteWithLogMessage(FunctionInvokeRequest request, RuntimeBindingProviderContext context, FunctionStartedMessage message, IDictionary`2 parameterLogCollector)
at Microsoft.Azure.Jobs.Host.Runners.WebSitesExecuteFunction.Execute(FunctionInvokeRequest request, RuntimeBindingProviderContext context)
In the dashboard, the message itself is shown with a valid RequestId present in the JSON, so I'm not sure why it's reported missing.
pianomanjh, I was able to reproduce the issue you are describing and I filed a bug. It seems that this failure only occurs in the blob name pattern, parameter binding is not affected.
The workaround for now is to use string instead of Guid for the property types.
Just found a solution to the blob issue i 0.3.0. Compared to version 0.2.0 you have to define the Blob to FileAccess.Write to make it work. It fixed the issue I described above to be able to stream to a blob

DataContract classes uninitialized at client side

I have the following class I'd like to send from my WCF (C#) service to my client (WPF):
[DataContract]
public class OutputAvailableEventArgs
{
[DataMember]
public int ID { get; set; }
[DataMember]
public string Message { get; private set; }
[DataMember]
public bool IsError { get; private set; }
public OutputAvailableEventArgs(int id) : this(id, false, "") { }
public OutputAvailableEventArgs(int id, string output) : this(id, false, output) { }
public OutputAvailableEventArgs(int id, bool isError, string output)
{
ID = id;
IsError = isError;
Message = output;
}
}
It's used by the service as follows:
var channel = OperationContext.Current.GetCallbackChannel<IClientCallback>();
channel.OutputAvailable(new OutputAvailableEventArgs(1, false, "some message"));
At the client side, the members get their default values.
I tried marking them with IsRequired attribute but now the OutputAvailable at the client is not called. The code at the service side seems to run smoothly (I didn't notice anything with the debugger).
How can I transfer a DataContract class with WCF while maintaining the members' values?
(I saw solutions that suggested to use OnSerialized and OnDeserialized but I don't need just a default constructor.)
I saw many different solutions for this problem. For other people's sake I'll write some of them down + what worked for me:
It seems that in some cases specifying the items' order solves the problem. Please see this SO question for full details.
If it's some default initialization you're after, you can use OnSerialized and OnDeserialized methods to call your initialization methods.
I also tried using the IsRequired attribute on my DataMembers but still didn't get my objects.
What worked for me was adding NameSpace property in the DataContract attribute. Apparently, In order to have the contracts be considered equal, you must set the Namespace property on the DataContract to the same value on both sides.

Return Entity Framework objects over WCF

We have a problem concerning Entity Framework objects and sending them through WCF.
We have a database, and Entity Framework created classes from that database, a 'Wallet' class in this particular situation.
We try to transfer a Wallet using this code:
public Wallet getWallet()
{
Wallet w = new Wallet();
w.name = "myname";
w.walletID = 123;
return w;
}
We need to transfer that Wallet class, but it won't work, we always encounter the same exception:
"An error occurred while receiving the HTTP response to localhost:8860/ComplementaryCoins.svc. 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."
We searched on the internet, and there is a possibility that the error is due to the need of serialization of Entity Framework-objects.
We have absolutely no idea if this could be the case, and if this is the case, how to solve it.
Our DataContract looks like this (very simple):
[DataContract]
public partial class Wallet
{
[DataMember]
public int getwalletID { get { return walletID; } }
[DataMember]
public string getname { get { return name; } }
}
Does anyone ever encountered this problem?
EDIT: Our Entity Framework created class looks like this:
namespace ComplementaryCoins
{
using System;
using System.Collections.Generic;
public partial class Wallet
{
public Wallet()
{
this.Transaction = new HashSet<Transaction>();
this.Transaction1 = new HashSet<Transaction>();
this.User_Wallet = new HashSet<User_Wallet>();
this.Wallet_Item = new HashSet<Wallet_Item>();
}
public int walletID { get; set; }
public string name { get; set; }
public virtual ICollection<Transaction> Transaction { get; set; }
public virtual ICollection<Transaction> Transaction1 { get; set; }
public virtual ICollection<User_Wallet> User_Wallet { get; set; }
public virtual ICollection<Wallet_Item> Wallet_Item { get; set; }
}
}
Thanks for helping us.
I had the same problem some time ago and the solution for this was:
The entity framework was returning a serialized class instead of normal class.
eg. Wallet_asfawfklnaewfklawlfkawlfjlwfejlkef instead of Wallet
To solve that you can add this code:
base.Configuration.ProxyCreationEnabled = false;
in your Context file.
Since the context file is auto generated you can add it in the Context.tt
In the Context.tt file it can be added around lines 55-65:
<#=Accessibility.ForType(container)#> partial class <#=code.Escape(container)#> : DbContext
{
public <#=code.Escape(container)#>()
: base("name=<#=container.Name#>")
{
base.Configuration.ProxyCreationEnabled = false;
<#
if (!loader.IsLazyLoadingEnabled(container))
{
#>
this.Configuration.LazyLoadingEnabled = false;
<#
Try specifying a setter for the properties, something like this :
[DataContract]
public partial class Wallet
{
[DataMember]
public int getwalletID { get { return walletID; } set { } }
[DataMember]
public string getname { get { return name; } set { } }
}
If it still doesn't work, you may consider creating an intermediate POCO class for this purpose, and use mapper library like AutoMapper or ValueInjecter to transfer the data from the EF objects.
The POCO class should have same properties as your EF class :
[DataContract]
public class WalletDTO
{
[DataMember]
public int walletID { get; set; }
[DataMember]
public string name { get; set; }
}
And modify your method to return this class instead :
public WalletDTO getWallet()
{
Wallet w = new Wallet(); // or get it from db using EF
var dto = new WalletDTO();
//assuming we are using ValueInjecter, this code below will transfer all matched properties from w to dto
dto.InjectFrom(w);
return dto;
}
Are you trying to recieve a IEnumerable<Wallets>? If - yes, please modify your server class that returns the IEnumerable by adding .ToArray() method

WCF object parameter loses values

I'm passing an object to a WCF service and wasn't getting anything back. I checked the variable as it gets passed to the method that actually does the work and noticed that none of the values are set on the object at that point. Here's the object:
[DataContract]
public class Section {
[DataMember]
public long SectionID { get; set; }
[DataMember]
public string Title { get; set; }
[DataMember]
public string Text { get; set; }
[DataMember]
public int Order { get; set; }
}
Here's the service code for the method:
[OperationContract]
public List<Section> LoadAllSections(Section s) {
return SectionRepository.Instance().LoadAll(s);
}
The code that actually calls this method is this and is located in a Silverlight XAML file:
SectionServiceClient proxy = new SectionServiceClient();
proxy.LoadAllSectionsCompleted += new EventHandler<LoadAllSectionsCompletedEventArgs>(proxy_LoadAllSectionsCompleted);
Section s = new Section();
s.SectionID = 4;
proxy.LoadAllSectionsAsync(s);
When the code finally gets into the method LoadAllSections(Section s), the parameter's SectionID is not set. I stepped through the code and when it goes into the generated code that returns an IAsyncResult object, the object's properties are set. But when it actually calls the method, LoadAllSections, the parameter received is completely blank. Is there something I have to set to make the proeprty stick between method calls?
Works just fine for me - could it be a silly typo??
In your OperationContract, you define LoadAllSections but in your client code, you attach an event handler to the proxy.GetAllSectionsCompleted event - maybe that's just the wrong handler? Shouldn't it be proxy.LoadAllSectionsCompleted ??
Marc
This seems odd, but it's what happens. I had another method on the service that returned a DataTable. Whenever a method tries to return a DataTable, the parameters passed in lose their values. Take out the method, and everything works. Odd.