I have written following code, but only first method in service shows up in client side but rest of two doesn't :(
any one guide me what could be the issue?
ServiceInterface:
[ServiceContract]
public interface IService1
{
[OperationContract]
claimantResponse SaveClaimant(claimant claimant);
[OperationContract]
claimantResponse RenewExpiry(claimantMin claimantMin);
[OperationContract]
claimantResponse getAccessCode(claimantMin claimantMin);
}
ServiceImplementation:
public class Service1 : IService1
{
public claimantResponse SaveClaimant(claimant claimant)
{
return new claimantBLL().SaveClaimant(claimant);
}
public claimantResponse RenewExpiry(claimantMin claimantMin)
{
return new claimantBLL().RenewExpiry(claimantMin);
}
public claimantResponse getAccessCode(claimantMin claimantMin)
{
return new claimantBLL().getAccessCode(claimantMin);
}
}
Data:
[DataMember]
public class claimantResponse
{
private List<string> _ErrorMessage = new List<string>();
[DataMember]
public List<string> ErrorMessage
{
get { return _ErrorMessage; }
set { _ErrorMessage = value; }
}
private List<int> _ErrorCode = new List<int>();
[DataMember]
public List<int> ErrorCode
{
get { return _ErrorCode; }
set { _ErrorCode = value; }
}
[DataMember]
public String FormStatus { get; set; }
[DataMember]
public DateTime ExaminationDate { get; set; }
[DataMember]
public String AccessCode { get; set; }
[DataMember]
public String Status { get; set; }
[DataMember]
public string temp2 { get; set; }
}
It shows two strange methods getdata and getdataobject instead of my own methods.. :(
Any help would be appreciated.
The code that you have posted will not compile. Due to the data member attribute on the class.
If you then press "run anyway" (cannot remember the exact text, but something close to that). Then it will run the last version of the code that compiled. The method names that you are seeing could have been in the original template that you used to create the service.
I resolved this problem by simply restarting Visual Studio 2012 :-)
My version of the problem was that renaming methods and removing the OperationContract attribute off an interface did not make a change to the methods I saw when I ran WCF test client. I even commented out a method and Visual Studio ran the debugger for that method! I restarted Visual Studio and it was back to normal.
I got solution to this problem and posting here so might help any body else with same scenario:
1) Removing [DataMember] attribute from the class and properties.
2) creating a new WCF simple service and putting same code worked.
i did remove datamember attribute from the old service but it was not working, so i assume my service was got corrupted because it was not showing any new method that a new service did :(
3) web.cofig would remain same from the time you you created sample of wcf and no change is required in this case.
Thank you!
So I had the same issue and could not see any new method that added regardless of Datacontract
first thing you need to have to expose your methods will be Data Annotation (attribute) OperationContract above your method inside the interface like the example below:
[ServiceContract]
public interface IService
{
[OperationContract]
Student_Identification GetStudentIdentification(int StudentId);
}
This was my first problem but I still couldn't see it, so I decide to update my service reference in the app where its being referenced
When I clicked Update Service Reference, an error message displayed saying it was unable to connect to server. In my case, the service was pointing to a different server. But I needed to point to my local computer, so I clicked Configure Service Reference
An there was my problem, the client address was set to a different url and not my local dev machine. I tried adding a host entry in my host file with the existing url the service was using and that still didn't fix my issue. So I went ahead and opened IIS since I have this project setup locally. selected my site, right clicked and selected Edit Bindings...
Click add and add the url address in the service and dont forgot to add it to you host file just in case. commonly located here -> C:\Windows\System32\drivers\etc
go back to the app thats referencing the service, right click service reference and select update service reference. This worked for me hopefully this helps someone on their journey.
Related
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.
I am currently using the WCF Web API and it is working great with synchronous tasks.
However, when I try and implement asynchronous operations using Task/Task like so:
[WebGet(UriTemplate = "landmark")]
Task<IEnumerable<Closest>> GetLandmarkAsync(float latitude, float longtitude)
{
return Task.Factory.StartNew(() => CalculateClosestThing(latitude, longtitude));
}
I am getting this error:
System.Threading.Tasks.Task`1[System.Collections.Generic.IEnumerable`1[ContentRepository.Data.Entities.Closest]] cannot be serialized because it does not have a parameterless constructor.
Now, the first thing I did was check the Closest Class and add a parameterless constructor like so:
public class Closest
{
public Closest() { }
public double Distance { get; set; }
public string Name { get; set; }
}
But I'm still getting the same error. I've tried everything and clearly there is a parameterless constructor on the class. Has anyone ever experienced this? Any ideas?
Ensure you new up a WebApiConfiguration obj (derived from HttpConfiguration) and set it as the default Http configuration with a call to routes.SetDefaultHttpConfiguration() in the host (I'm using an MVC host).
I had the same problem as you before I switched from HttpConfiguration to WebApiConfiguration.
For more details see here.
Give these a read:
http://arbel.net/2011/06/04/wcf-tasks/
http://msdn.microsoft.com/en-us/library/ms730059.aspx
http://www.dotnetcurry.com/ShowArticle.aspx?ID=237
I'm brand new to OData and WCF data services so this might be an easy problem. I'm using VS Web Developer Express 2010 where I have a very simple WCF Data Service hosted in a console app. It's returning an IQuerable collection of a simple 'Study' class from a repository (located in a separated dll project), which in turn retrieves 'Study' classes from a db project in another dll (so 3 projects in the solution).
I also have an 'Experiment' class in the db project and there can be multiple Experiments in a Study. When I exclude the Experiment class from the Study everything works and I get data coming back. The problem happens when I add a List collection to the Study class, then I get a runtime error when I try to run the service. In Firebug the error is '500 Internal Server Error', and the message in the browser is 'Request Error. The server encountered an error processing the request. See server logs for more details.'
I have IIS 7 and I also just installed IIS 7.5 but again it's brand new to me, so I can't figure out where the service is hosted or where to view the server / web logs. There are only IIS 7 logs visible in 'C:\inetpub\logs\LogFiles\W3SVC1'. The VS web server (Cassini) doesn't start when I run the app, so this suggests it's being hosted in IIS 7.5 (?).
So
- how do I return child classes / complex objects?
- how do I know where my service is hosted and where can I find the server logs?
Here's the host app:
using MyStudyRepository;
using MyStudyDB;
namespace MyStudyService
{
public class Program
{
public static void Main(string[] args)
{
string serviceAddress = "http://localhost:998";
Uri[] uriArray = { new Uri(serviceAddress) };
Type serviceType = typeof(StudyDataService);
using (var host = new DataServiceHost(serviceType,uriArray))
{
host.Open();
Console.WriteLine("Press any key to stop service");
Console.ReadKey();
}
}
}
public class StudyDataService : DataService<StudyRepository>
{
public static void InitializeService(IDataServiceConfiguration config)
{
config.SetEntitySetAccessRule("*", EntitySetRights.AllRead);
}
}
}
Here's the repository:
using MyStudyDB;
namespace MyStudyRepository
{
public class StudyRepository
{
List<Study> _List = new List<Study>();
//Add constructor to populate myStudies list on creation of class
public StudyRepository()
{
for (int i = 1; i < 5; i++)
{
Study myStudy = new Study() { ID = i, StudyOwnerId = i, StudyName = "Study" + i.ToString() /*, Experiments = null */ };
_List.Add(myStudy);
}
}
public IQueryable<Study> Studies
{
get
{
return _List.AsQueryable<Study>();
}
}
}
}
And here's the DB:
namespace MyStudyDB
{
public class Study
{
public int ID { get; set;}
public int StudyOwnerId { get; set; }
public string StudyName { get; set; }
//public List<Experiment> Experiments { get; set; }
}
public class Experiment
{
public int ID { get; set; }
public string Name { get; set; }
public int StudyId { get; set; }
}
}
To debug the WCF Data Service please refer to this blog post: http://blogs.msdn.com/b/phaniraj/archive/2008/06/18/debugging-ado-net-data-services.aspx
As to why the collection of Experiment doesn't work, there are two reasons:
The Experiment class is not recognized as an entity type because there's no entity set for it. (Entity set is the IQueryable property on your repository class, which you don't have). As a result the Experiment class is only recognized as a complex type.
The currently released version of WCF Data Services doesn't support MultiValues, MultiValue is effectively a collection of primitive or complex types.
So you have two way to "fix" this. Either make sure that Experiment is in fact an entity, by adding IQueryable property on your repository class.
Or use the latest CTP (http://blogs.msdn.com/b/astoriateam/archive/2011/06/30/announcing-wcf-data-services-june-2011-ctp-for-net4-amp-sl4.aspx) which does support MultiValues.
Thanks! And I guess it is missing the DataServiceKey attribute on the class as follows:
[DataServiceKey("ID")]
public class Study
{
.....
}
This is one of the classes in Interface file.
[DataContract]
public class ClassX
{
public ClassX()
{
ClassXParameters = new List<ClassXParameter>();
}
public void Add(string name, string value)
{
ClassXParameters.Add(new ClassXParameter() { Name = name, Value = value });
}
[DataMember]
public List<ClassXParameter> ClassXParameters { get; set; }
}
[DataContract]
public class ClassXParameter
{
[DataMember]
public string Name { get; set; }
[DataMember]
public string Value { get; set; }
}
on the client I'm trying to do something like this
ClassX classx = new ClassX();
classx.Add("testname", "testvalue");
But this .Add method is not even visible.
currently I'm doing
ClassX classx = new ClassX();
List<ClassXParameter> params = new List<ClassXParameter()>;
params.add(new ClassXParameter() {Name="testname", Value="testvalue"});
classx.ClassXParameters = params;
Is there anyway I can do what I'm trying to do?
Note: I am not sure why some of the text above are in bold.
If you autogenerate the client code from scratch, it will generate a new class, which contains those members and properties that are marked with DataContract.
If you have methods that you want available on the client, you can accomplish this by putting the DataContract types in an own assembly, which you reference from both the server and the client. When you generate the service reference you have to choose the option to reuse existing classes instead of generating new ones.
Often it is suitable to put data validation rules in the data contract classes property setters. Reusing the data contract assembly in the client will cause the data validation to occur directly on the client, without the need for a roundtrip. It also causes the error in a place where it is much easier to spot than if it is reported as deserialization error.
Data Contracts are for data only. Any methods will not be visible on the client.
The bold was because of the "-----".
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.