I'm new to working with WCF and i'm struggling to understand whats happening.
I'm trying to retrieve data from my service, which in turn grabs it from the database. To simplify things I wanted to return an object containing the data so that it could just be used immediatly within the UWP app. However, I'm running into the following error when I try to consume the service:
Cannot implicitly convert type 'MBCMobile.ServiceReference1.TaskBreakdown_GetDataResponse' to 'MBCMobile.ServiceReference1.JobTestObject'
The following code is what I'm using:
[ServiceContract]
public interface IService1
{
[OperationContract]
JobTestObject TaskBreakdown_GetData(int task, int appliance, int job);
}
[ServiceBehavior(AddressFilterMode = AddressFilterMode.Any)]
public class Service1 : IService1
{
public JobTestObject TaskBreakdown_GetData(int task, int appliance, int job)
{
JobTestObject jobData = data.TaskBreakdown_GetData(task, appliance, job); //object returned from sql query
return jobData;
}
}
To consume my service im using the following:
private async void GetString()
{
ServiceReference1.Service1Client service = new ServiceReference1.Service1Client();
JobTestObject datalist = await service.TaskBreakdown_GetDataAsync(6153, 18876, 18111);
}
JobTestObject has the same format in both the service and the UWP app. The service version literally exists as a collection of get/set methods and nothing else. The app version has additional methods, but the exact same get/set methods. I've tried using ServiceReference1.JobTestObject instead to see if that helps but to no avail. I expect that it might be a little naive of me to think an object can be passed to the client this way.
I also tried just returning a list of strings and got a similar error.
I've managed fine in the past with retrieving single values from the service, but now that I want to get multiple values at once I can't understand what I'm doing wrong. Sadly most of the solutions I've found don't relate to UWP apps
Update: As requested
[DataContract]
public class JobTestObject
{
int appliance_id, manu_id, model_id, landlord_app, applianceType_id,
[DataMember]
public int ApplianceType { get { return applianceType_id; } set { applianceType_id = value; } }
[DataMember]
public int Appliance_ID { get { return appliance_id; } set { appliance_id = value; } }
[DataMember]
public int ApplianceManufacturer { get { return manu_id; } set { manu_id = value; } }
[DataMember]
public int ApplianceModel { get { return model_id; } set { model_id = value; } }
}
Related
I've a WCF service with one method which will be called from multiple web API controllers like in the below code.
public string Print(PdfPrinterRequest _request)
{
PdfPrinterService.PdfPrinterClient _Client = new PdfPrinterService.PdfPrinterClient();
PdfPrinterResponse _response = new PdfPrinterResponse();
return _Client.Print(_request.Document, out _pdfResponse);
}
PdfPrinterRequest(Document class) is the entity which I'm passing to get the response message from WCF service.Currently the document class holds few properties(REquest Header). I would like to call the same Print method from other API and pass type 'Customer' to WCF service. How can i achieve this? Can anyone please suggest me the correct implementation?
Below is my WCF service code,
public class PdfPrinterService : IPdfPrinter
{
public PdfPrinterResponse Print(PdfPrinterRequest request)
{
return PdfPrinterFacade.PrintPdf(request);
}
}
public static PdfPrinterResponse PrintPdf(PdfPrinterRequest request)
{
PdfPrinterResponse response = new PdfPrinterResponse();
//Process the request and send back the response message
}
[MessageContract]
public class PdfPrinterRequest
{
private Document _document;
[MessageBodyMember]
public Document Document
{
get { return _document; }
set { _document = value; }
}
}
How to pass a dynamic class object as a parameter in place of PdfPrinterRequest which is no bound to only one type(Document)? Please suggest.
Thanks,
If this service does not need to be interoperable, you can switch to NetDataContractSerializer, which uses full .NET type information, and is able to serialize many more types (but not any type - that's impossible).
Grab the UseNetDataContractSerializerAttribute from this answer and apply like so:
[UseNetDataContractSerializer]
public class PdfPrinterService : IPdfPrinter
{
public PdfPrinterResponse Print(PdfPrinterRequest request)
{
return PdfPrinterFacade.PrintPdf(request);
}
}
[MessageContract]
public class PdfPrinterRequest
{
[MessageBodyMember]
public object Document { get; set; }
}
I am developing a wcf web service. It was working correctly during unit testing. A few days back, I changed the default namespace from 'tempuri' as explained in this link: http://blog.rebuildall.net/2010/11/10/wcf_service_namespaces and also added 'Order' Property to the datamembers i.e. like [DataMember(Order = 1)] of both request and response classes. Now in one OperationContract, some parameters are being read as null at server side even though value is passed at client side. I also noticed that the responses of a couple of OperationContracts were showing empty tags when there should have been value in those tags.
On searching, I found blog with a similar problem, but what caused their problem was a name mismatch of a parameter in client and server side. The link to the blog is : http://blog.functionalfun.net/2009/09/if-your-wcf-service-is-unexpectedly.html
Can anyone guide me here. Thanks in advance
I dunno if anyone else manages to get this error the way I did, but this was the problem:
I had defined my classes like below:
public class CompositeType
{
private bool boolValue;
private string stringValue = "";
[DataMember]
public bool BoolValue
{
get { return boolValue; }
set { boolValue = value; }
}
[DataMember]
public string StringValue
{
get { return stringValue; }
set { stringValue = value; }
}
}
By removing those variable declarations and using auto-property syntax, I was able to get past the issue. i.e like :
public class CompositeType
{
[DataMember]
public bool BoolValue
{
get;
set;
}
[DataMember]
public string StringValue
{
get;
set;
}
}
I have this object:
public class Announcement
{
public int Id { get; set; }
public DateTime DateSent { get; set; }
private IList<string> _recipients;
public IList<string> Recipients
{
get { return _recipients; }
set { _recipients = value; }
}
public string RecipientsString
{
get { return String.Join("\n", _recipients); }
set { _recipients = value.Split('\n').ToList(); }
}
}
I can populate this object with the DateSent and RecipientString (a string of email addresses separated by \n) and save it to the database with no problems.
Now I want to move this to a web service so we can use it across multiple apps.
I created the exact same object in the webservice, and testing locally (on the service) everything works as expected.
But if I populate the object on the client and pass it to the service to be saved, the RecipientString is always empty (not null). The DateSent is fine.
I'm guessing the data is getting lost in serialization, but I don't know why, or how to solve this. I thought also, it could have something to do with the # in the email address, but I've ruled that out. Any suggestions?
This happens because de WSDL that is generated to describe your service can't describe the function that is used in your get and set functions. I suggest you keep RecipientsString as a common property, and create a private method GetRecipients on your class that processes the RecipientsString value and returns the list you need.
Use RecipientsString without backing field.
I made some changes to my interface for a RIA service, but SL is not getting them when I do an update.
Basically changed a few from void to bool so I could check for completion.
I've tried deleting, getting again, etc.
No matter what I do, when I call my client side context it still shows the old interface.
[ServiceContract]
public interface IUploadService
{
[OperationContract]
bool UploadFile(CrmFileUpload fileUpload);
}
public partial class CrmFileUpload
{
public string FileName { get; set; }
public byte[] Chunk { get; set; }
}
Updated code:
public void TestMe(string testString)
{
_context.TestMethodAsync(testString); //this shows void, but everything in the WCF is a string
}
I have a WCF service that passes back and forth the following DataContracts:
[DataContract]
public class RequestWrapper
{
[DataMember]
public FooDataContract FooDataContract;
}
[DataContract]
public class ResponseWrapper
{
[DataMember]
public FooDataContract FooDataContract;
}
[DataContract]
public class FooDataContract
{
public FooDataContract(string data, Guid id)
{
Data = data;
ID = id;
}
[DataMember]
public string Data { get; set; }
[DataMember]
public Guid ID { get; set; }
}
It's called via a proxy class like this:
void CallService(string data)
{
var id = Guid.NewGuid();
var response = proxy.CallService(new RequestWrapper
{
new FooDataContract(data, id);
});
}
This is then passed (over the service) to the database via a repository using EF:
public void RepoMethod(FooDataContract foo)
{
var guid = foo.ID; // - Breakpoint here shows all zeros!
efContext.DoSomething(foo.Data, foo.ID);
}
Here's the service call:
public ResponseWrapper CallService(RequestWrapper request)
{
var foo = request.FooDataContract;
repository.RepoMethod(foo);
var response = new ResponseWrapper{ FooDataContract = foo };
return response;
}
Here's the proxy:
public class Proxy : IMyService
{
static readonly ChannelFactory<IMyService> channelFactory =
new ChannelFactory<IMyService>("IMyService");
ResponseWrapper CallService(RequestWrapper request)
{
return channelFactory.UseService(s => s.CallService(request));
}
}
internal static class UseServiceFunction
{
internal static R UseService<T, R>
(this ChannelFactory<T> channelFactory, Func<T, R> useService)
{
var service = channelFactory.CreateChannel();
try
{
R response = useService(service);
return response;
}
finally
{
var channel = service as ICommunicationObject;
try
{
if (channel.State != CommunicationState.Faulted) channel.Close();
}
catch { channel.Abort(); }
}
}
}
I've put a watch on the Guid in the VS debugger. When the service is called from a client web application, the generated Guid is a valid Guid of seemingly random hex characters. Great, that's working.
But when the data is serialized, goes over the wire, and comes out the other side (in my repository), the Guid is all zeros!
I've double, triple checked that the Guid is indeed marked with the [DataMember] attribute. I'm wondering if the extra layer of DataContract (how a FooDataContract is wrapped with the RequestWrapper data contract) is causing a serialization issue?
I think your problem here is that the constructor you've made in your DataContract class doesn't get passed to the proxy on the client side. WSDL won't know anything about this. Think of your data contracts as just a place to stick data with no other functionality. To confirm, you can look in the reference.cs class that got generated in the client when you added the service reference.
I'd suggest re-writing the code so that you explicitly set each of the values in your data contract rather than relying on the constructor.
You can also write a hand coded proxy that has whatever behavior you want and then share that file with the client. That would work, but then you'll be more tightly coupling your client to your service.
Turns out, my translation layer wasn't updated to convert between the DTOs! Whooooops!