I have written a basic WCF service that uses SubSonic for data retrieval.
After publishing the service I am consuming it in a C# application. When calling the method that uses that SubSonic query, I get back the right number of objects from the database, but none of them contain the database properties and their values. It looks like only SubSonic properties.
The SubSonic DAL is contained in a separate project that is referenced in the WCF service project.
WCF service interface:
[OperationContract]
GeoLocationCollection GetGeoLocations(long websiteID);
Worker method:
public GeoLocationCollection GetWebsiteGeoLocations(long websiteID)
{
GeoLocationCollection locationsCollection = new Select()
.Where(GeoLocation.Columns.WebsiteID).IsEqualTo(1)
.From(GeoLocation.Schema)
.ExecuteAsCollection<GeoLocationCollection>();
return locationsCollection;
}
Both the GeoLocationCollection and GeoLocation have been automatically decorated with [Serializable].
The service is consumed as follows:
MyService.MyServiceClient client = new MyService.MyServiceClient();
var result = client.GetWebsiteGeoLocations(1);
foreach (MyService.GeoLocation location in result)
{
// do stuff
}
So once again, why can I not see any of my actual table properties/values in location?
WCF services require [DataContract] + [DataMember] attribute and not [Serializable]. This maybe the reason for you to not get the attribute values.
Related
My WCF contains two methods. The first is simple which returns string and takes string as parameter, but in second method I am passing a class containing properties as parameter and return string.
When I comment second method then I am able to get WCF_Masters.ServiceClient object in client application but after uncommenting 2nd method I am unable to get that object.
I get only CompositeType instead of ServiceClient of My WCF service whose name is WCF_Masters.
Note that I am trying to consume WCF in WPF Windows application.
How can I get rid of this issue?
Edit
My WCF methods are:
public String GetMessage(string vName)
{
return "Hello world from " + vName;
}
public String SaveEmployee(EmployeeMasterSC vEmployeeMasterSC)
{
String mReturnMsg = string.Empty;
EmployeeMasterDAL vEmployeeMasterDAL = null;
vEmployeeMasterDAL = new EmployeeMasterDAL();
mReturnMsg = vEmployeeMasterDAL.SaveEmployee(vEmployeeMasterSC);
//mEmpDset.EmployeeData = Mdset; return mReturnMsg;
}
If I understood you correctly, you should not be adding a reference to your WPF DLL in your WCF service. Define the model in your service and then instantiate that model (by reference) in your WPF application, which is consuming the service.
I believe the reason it works when you comment out the 2nd method is that your 1st method has no reference to class structures defined in the WPF DLL.
Got the solution guys, It was the issue of database name I have Written incorrectly "AirportPortal" instead of "DB_AirportPortal" in WCF while inserting records into database
I am in the middle of big web application, I use Entity Framework as my data service, now we need some windows application to work with our data, so I want to give them a service with WCF
But when my client wants to get service some error is happened from my public property which I use for caching Entity Model
public partial class DepositEntities : ObjectContext
{
public static DepositEntities Current
{
get
{
DepositEntities oc =
HttpContext.Current.Items["ObjectContext"] as DepositEntities;
if (oc == null)
{
oc = new DepositEntities();
HttpContext.Current.Items["ObjectContext"] = oc;
}
return oc;
}
}
}
I know the problem is from this line, after I debug my code
DepositEntities oc = System.Web.HttpContext.Current.Items["ObjectContext"] as DepositEntities;
When I change my Current property body to some thing like this
public static DepositEntities Current
{
get
{
DepositEntities oc = new DepositEntities();
return oc;
}
}
everything is OK when I get data from services I have no problem
But everywhere I have join in my codes I have problem because It thinks there are different data source because of new DepositEntities();
You're most likely experiencing problems because WCF doesn't have HttpContext.Current. Read more about contexts in WCF - this question may be a good start: http://social.msdn.microsoft.com/Forums/en/wcf/thread/27896125-b61e-42bd-a1b0-e6da5c23e6fc.
I also think it would be better for you to manage lifetime of an ObjectContext with a DI Container (ie. Castle Windsor). Thanks to this, it won't be necessary to expose static property Current which is a problem for WCF service, unit tests, etc.
Check out "Hosting WCF Services in ASP.NET Compatibility Mode" in wcf service and ASP.NET. It explains how to get a valid HttpContext in a wcf service.
I have this scenario where a webservice method I'm consuming in C# returns a Business object, when calling the webservice method with the following code I get the exception "Unable to cast object of type ContactInfo to type ContactInfo" in the reference.cs class of the web reference
Code:
ContactInfo contactInfo = new ContactInfo();
Contact contact = new Contact();
contactInfo = contact.Load(this.ContactID.Value);
Any help would be much appreciated.
This is because one of the ContactInfo objects is a web service proxy, and is in a different namespace.
It's a known problem with asmx-style web services. In the past I've implemented automatic shallow-copy to work around it (here's how, although if I were doing it again I'd probably look at AutoMapper instead).
For example, if you have an assembly with the following class:
MyProject.ContactInfo
and you return an instance of it from a web method:
public class DoSomethingService : System.Web.Services.WebService
{
public MyProject.ContactInfo GetContactInfo(int id)
{
// Code here...
}
}
Then when you add the web reference to your client project, you actually get this:
MyClientProject.DoSomethingService.ContactInfo
This means that if, in your client application, you call the web service to get a ContactInfo, you have this situation:
namespace MyClientProject
{
public class MyClientClass
{
public void AskWebServiceForContactInfo()
{
using (var service = new DoSomethingService())
{
MyClientProject.DoSomethingService.ContactInfo contactInfo = service.GetContactInfo(1);
// ERROR: You can't cast this:
MyProject.ContactInfo localContactInfo = contactInfo;
}
}
}
}
It's on that last line that I use my ShallowCopy class:
namespace MyClientProject
{
public class MyClientClass
{
public void AskWebServiceForContactInfo()
{
using (var service = new DoSomethingService())
{
MyClientProject.DoSomethingService.ContactInfo contactInfo = service.GetContactInfo(1);
// We actually get a new object here, of the correct namespace
MyProject.ContactInfo localContactInfo = ShallowCopy.Copy<MyClientProject.DoSomethingService.ContactInfo, MyProject.ContactInfo>(contactInfo);
}
}
}
}
NOTE
This only works because the proxy class and the "real" class have exactly the same properties (one is generated from the other by Visual Studio).
As several of the other answers have suggested, it is because .NET sees them as two different classes. I personally would recommend using something like AutoMapper. I've been using it, and it seems pretty awesome. You can copy your objects in 1-2 lines of code.
Mapper.CreateMap<SourceClass, DestinationClass>();
destinationInstance = Mapper.Map<SourceClass, DestinationClass>(sourceInstance);
Actually this is not a bug. It's a problem with the version changes of your own project!
Because your final run don't use the original imported references on compile!
For example, I was making a chat server, client. I used a packet structure to transmit data on client project.
Then imported the same reference to server project.
When casting Packet packet = (Packet)binaryFormatter.Deserialize(stream); I got the same error. Because the actual running reference at server project is not the reference now at client project! Because I have rebuilt client project many times after!
In casting <new object>=(<new object>) <old object> always the new object needs to be a newer or same version as the old object!
So what I did was I built a separate project to create a DLL for the Packet class and imported the DLL file to both projects.
If I did any change to Packet class, I have to import the reference to both client and server again.
Then the casting won't give the above exception!
How are you referencing the class in your web service project as well as consumer project? If you have simply used a file link, this could well explain the cause of the error. The way serialiasation works for .NET (Web Services or otherwise I believe) is by using reflection to load/dump the data of an object. If the files are simply linked, then they are actually getting compiled to different types in different assemblies, which would explain why you have the same name but can't cast between them. I recommend creating a 'Core' library which both the web service and consumer project references, and contains the ContactInfo class which you use everywhere.
This isn't a problem - it's a feature.
They are two independent classes. Compare the two, and notice that the proxy class has none of the constructors, methods, indexers, or other behavior from the original class. This is exactly the same thing that would happen if you consumed the ASMX service with a Java program.
Seems like you have two different classes on both ends. Your application has ContactInfo class and your webservice also have the ContactInfo class. Both are two completely different classes. One way is to use the WebService class on your side. If you are using ContactInfo inside your web service then it will be serialized and will be available on the client side for use.
You can also modify your References.cs file generated by Visual Studio when the web reference is added. If you remove the proxy generated classes and add a reference (using statements) to your personal classes, you'll be able to use them straight away, without shallow copy / reflection or heavy mapping. (but you'll have to re-apply your modification if you regenerate the proxy layer).
I also tried to serialize the proxy object and deserialize them back in my DTO classes but it was quite heavy resources wise so I ended up modifying the References cs generated layer.
Hope it will help other people coming here :)
Kindly.
I have created a SoapExtension class to capture the soap request and response from specific web service calls. In order to put this SoapExtension into effect, I have to add an attribute to the method in the generated proxy client.
For example, I've added the AuditSoapCapture attribute to this method:
[System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://blahblah.com/webservices/AddressSearch", RequestNamespace = "http://blahblah.com/webservices/", ResponseNamespace = "http://blahblah.com/webservices/", Use = System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle = System.Web.Services.Protocols.SoapParameterStyle.Wrapped)]
[blahblah.TriadLite.Core.AuditSoapCapture]
public System.Data.DataSet AddressSearch(string HouseNumber, string StreetName, string ZipCode) {
object[] results = this.Invoke("AddressSearch", new object[] {
HouseNumber,
StreetName,
ZipCode});
return ((System.Data.DataSet)(results[0]));
}
I am looking for a way to add this attribute to specific methods without modifying the generated client proxy, as they will get lost when we regenerate. Can I do this in a another partial class or interface or some other way?
Thanks!
Unfortunately, you'll need to modify the proxy code. The other possibilities you mention will not work - a parial class will not overwrite existing functionality, and there is no way that I'm aware of getting an interface to do what you need (compounded by the fact that there is no way to even let the proxy generator know that you intend to implement an interface).
Something that I've done in the past, in a situation where you have access to the source of the webservice, is to write a little app that will parse the code (as text) in the .asmx.cs file of the webservice to extract the names of all the methods that are tagged with [WebMethod]. Then the app "fixes up" the References.cs by inserting appropriate attributes onto the proxied methods, based on some settings file or somesuch. This works well because the naming conventions in the proxy map very neatly to the method names in the original service.
I may just end up injecting my SoapExtension by putting it into the Web.config. This will cause it to be run on every WS call without a client proxy method attribute. Then, I will modify the SoapExtension to look up the called WS method name on a list, and if it is on the list, then do the rest of the SoapExtension logic. I figure the hit on the list in this small volume application isn't going to kill performance.
6 years ago this was posted... So not sure if this will help anyone at this point.
I ran into something similar with a call to an old SOAP web service that had a dynamically generated proxy class that we didn't want to modify as it was auto-generated from the wsdl by the project. In order to solve this problem here is what we did.
The proxy class generated by wsdl.exe is a partial class. We extended this class like so to add a property with the information we wanted to access in the soapextension. You can add as many properties as you want...
partial class mysoapwebservice
{
public string myproperty{ get; set; }
}
in the web.config we registered the soap extension globaly on the project
<webServices>
<soapExtensionTypes>
<add type="MySoapExtension" priority="1" group="Low"/>
</soapExtensionTypes>
</webServices>
In the code were we created the web service object 'mysoapwebservice' we set the value of the property we needed.
In the soapextension you can get a reference to the web service that was called as well as the values. You can also determine the method call.
`
public class MySoapExtension: SoapExtension
{
public override void ProcessMessage(SoapMessage message)
{
switch (message.Stage)
{
case SoapMessageStage.BeforeSerialize:
{
// web service client object
var webserviceobject= ((SoapClientMessage)message).Client;
// method from web service that was called
var calledMethod = (SoapClientMessage)message).MethodInfo;
// checked the client type of webserviceobject and
//added method / property specific logic here
}
}
}
// other soap extension code
}
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class)]
public class CriptoExtensionAttribute : SoapExtensionAttribute
[CriptoExtension]
public partial class MainService{
if you have an entity which is reference in the client and a webservice like this
public class Post
{
public int ID {get; set;}
string Data {get; set;}
}
public class MyService: System.Web.Services.WebService
{
[WebMethod]
public int Write (Post post)
{
//Do stuff
}
}
on the client in order to use the entity you to instantiate from the proxy class
public void ClientMethod()
{
var post = new proxyclass.Post();
//fill post
new ProxyClass.Myservice().Write(post)
}
how can i use my domain entity to call the webservice?
public void ClientMethod()
{
var post = new Post();
//fill post
new ProxyClass.Myservice().Write(post)
}
Basically, you can't - with regular web-services, at least... the proxy class is completely separate. However, the above is possible with WCF, where you don't actually need proxy classes at all (however, for SOA purity it is a good idea to use them).
You could use reflection (etc) to copy the properties between your domain entities and the proxies, but it is quite hard to get this 100% right (although xml serialization should work [in theory] as an intermediate language).
So; if you want to use assembly sharing; consider using WCF, which supports this ;-p
To get hold of a service without using a proxy layer, you can do tricks like:
public class WcfClient<T> : ClientBase<T> where T : class
{
public T Service { get { return base.Channel; } }
}
(this will access the default configuration from the app.config; for more control you need to add a few constructor overloads matching to the base constructor overloads)
Then:
interface IFoo {void Bar();}
...
using(WcfClient<IFoo> client = new WcfClient<IFoo>()) {
client.Service.Bar();
}
I suspect that one of these might answer your qestion. The common theme is wsdl.exe /sharetypes and svcutil /reference.
Managing 2 web references with shared class dependency in a .NET project
Force .NET webservice to use local object class, not proxy class
.Net Consuming Web Service: Identical types in two different services
How to get a webserice to serialize/deserialize the same type in .net
.NET SOAP Common types
wsdl.exe /sharetypes
You should use WCF for new development whenever possible.
However, you should reconsider your reasons for wanting to use your domain class on the client. It does violate the principles of SOA by exposing to the client some details of the implementation of the service. Why should the client know anything about your entity classes, beyond the data that they contain?
For instance, your entity classes may contain methods to save the entity to the database. Why does your client need access to that method?
Also, one of the principals of SOA is to interoperate with different platforms. As soon as you require your client to use your (.NET) entity, you prevent a Java or PHP client from being written to use your service.
You may have good enough reasons to overcome such objections, but I recommend that you think it through and make sure your reasons are good enough.
For cases like this you're better to use json for sending and receiving data to and from web service.
Newtonsoft.json is the best json serializer for .Net. so you should change your Write method like below:
public void ClientMethod()
{
var post = new Post();
//fill post
new ProxyClass.Myservice().Write(JsonConvert.SerializeObject(post))
}