I'm a newbie to WCF technology. My current problem is that my windows forms app isn't getting a respond from wcf program. Here is the code for my windows forms app :
WCFService.PMSService obj = new WCFService.PMSService();
string xx = obj.Test("Hello");
MessageBox.Show(xx);
My windows forms app hangs on this line -> string xx = obj.Test("Hello");
Here is the code for wcf my program :
Interface/Declaration page
// NOTE: You can use the "Rename" command on the "Refactor" menu to change the interface name "IService1" in both code and config file together.
[ServiceContract]
public interface IPMSService
{
[OperationContract]
string DetermineGender(PersonalInfo pInfo);
[OperationContract]
string Test(string val);
}
[DataContract]
public enum Gender
{
[EnumMember]
Male,
[EnumMember]
Female,
[EnumMember]
None
}
// Use a data contract as illustrated in the sample below to add composite types to service operations
[DataContract]
public class PersonalInfo
{
[DataMember]
public string name
{
get { return name; }
set { name = value; }
}
[DataMember]
public string surname
{
get { return surname; }
set { surname = value; }
}
[DataMember]
public string idNo
{
get { return idNo; }
set { idNo = value; }
}
Implementation page
// NOTE: You can use the "Rename" command on the "Refactor" menu to change the class name "Service1" in code, svc and config file together.
public class PMSService : IPMSService
{
public string DetermineGender(PersonalInfo pInfo)
{
Gender Result = Gender.None;
int idNo = Convert.ToInt32(pInfo.idNo.Substring(6, 4));
if (idNo >= 5000)
Result = Gender.Male;
else
Result = Gender.Female;
return Result.ToString();
}
public string Test(string val)
{
return "U passed " + val;
}
}
Does anybody know the possible cause ?
The best suggestion (and perhaps so obvious that many overlook) for someone new to WCF is to become familiar with WCF Tracing and Message Logging. The WCF tracing functionality provides a relatively simple, built-in method to monitor communication to/from WCF services. For test and debugging environments, configure informational or verbose activity tracing and enable message logging. The combination of activity tracing and message logging should prove beneficial when initially deploying and testing new services or adding new operations and/or communication bindings to existing services.
The following links provide a good overview:
http://msdn.microsoft.com/en-us/library/ms733025.aspx
http://msdn.microsoft.com/en-us/library/aa702726.aspx
Related
I want to create and consume a WCF Service in Silverlight. I have created a service that returns this model from a database:
namespace SilverlightWithWCFService.Web
{
[DataContract]
public class Customer
{
[DataMember]
public string CustomerName { get; set; }
[DataMember]
public string CompanyName { get; set; }
[DataMember]
public string ContactName { get; set; }
}
}
The service looks like this:
namespace SilverlightWithWCFService.Web
{
[ServiceContract(Namespace = "")]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class SampleService
{
[OperationContract]
public List<Customer> CustomerList()
{
var custList = new List<Customer>();
// populate custList
return custList;
}
}
}
}
In my Silverlight application, I added a Service Reference. This method calls the service operation:
public Page()
{
InitializeComponent();
SampleServiceClient client = new SampleServiceClient();
client.CustomerListCompleted += new EventHandler<CustomerListCompletedEventArgs>(client_CustomerListCompleted);
client.CustomerListAsync();
}
void client_CustomerListCompleted(object sender, CustomerListCompletedEventArgs e)
{
CustomerGrid.ItemsSource = e.Result;
}
So my question is: I don't know how the Silverlight work with WCF. Do I have to serialize something on WCF side and deserialize the return value on client side? If so, what code is missing? (Where?)
UPDATE:
I think based on some online questions. Should I deserialize the returned e.Result in the completed event code?
Do I have to serialize something on WCF side and deserialize the return value on client side?
No, when you consume the webservice the underlying code will do all that for you.
Don't get hung up on it being Silverlight. Just think of Silverlight as the same as a console application. Whatever one has to do in the console app to consume the webservices, one will have to do in Silverlight. The only difference is that you will need to handle the calls in an async manner, but that is separate from the consuming of the webservice which your question pertains.
Note there was a competing technology to do all the updates of the webservice during a compile. That was called RIA services and that is a different animal all together.
I would recommend you use WCF web services, but update the size of the send/receive buffers for you will max those out easily on any true data transfers.
Over the last couple of days I've been researching WCF. I've been reading various discussions and following a number of different walkthroughs, most notably the one linked below.
WCF Getting Started Tutorial
I'm now trying to convert these skills into a different scenario. The file structure is exactly the same as what was stated in the aforementioned walkthrough. There is one WCF Service Library, a Host (Console Application) and a Client (Console Application). The host is setup in the same manor as the walkthrough, the client has been altered to allow user input instead of hardcoded values and the WCF code has been provided below.
After a value is provided the WCF Library will run until the following line var userData = repository.GetById(userId);. When the breakpoint is reached and I step over, an exception is thrown stating that the ConnectionString expected doesn't exist. I've tested putting the connection string in the Client and WCF projects but to no avail. I've also ensured EntityFramework and Service.Configuration DLLs are also added as references.
It's possible I am missing another DLL, App.config setting or I've completely messed up and misinterpretted what I can do with a WCF Service Library so I'm looking for some advice on how to rectify the issue in the previous paragraph or a link which helps me understand the problem
IService.cs Code
[ServiceContract(Namespace = "....")]
public interface IUser
{
[OperationContract]
User GetUser(int userId = 0);
}
[DataContract]
public class User
{
[DataMember]
public int UserId { get; set; }
[DataMember]
public string UserName { get; set; }
[DataMember]
public string FirstName { get; set; }
[DataMember]
public string LastName { get; set; }
}
Service.cs Code
public class UserService : IUser
{
public User GetUser(int userId = 0)
{
User user = null;
using (var context = new Context())
{
var repository = new Repository(context);
var userData = repository.GetById(userId);
if (userData != null)
{
user = new User
{
UserId = userId,
FirstName = userData.CustomerFirstName,
LastName = userData.CustomerSurname,
UserName = userData.CustomerEmail
};
Console.WriteLine("UserId : {0}", userId);
Console.WriteLine("FirstName : {0}", userData.CustomerFirstName);
Console.WriteLine("LastName : {0}", userData.CustomerSurname);
Console.WriteLine("UserName : {0}", userData.CustomerEmail);
}
}
return user;
}
}
Edit:
<add name="CONTEXT"
connectionString="Server=SERVER;Database=DATABASE;uid=DATABASE;pwd=DATABASE;"
providerName="System.Data.SqlClient" />
Your connection string must be set in the App.config of the executing assembly, not in the assembly directly using it. This means that although your service implementation (Service.cs) is located in your WCF Library assembly, the connection string must be located in the App.config of your host project. If you declare an App.config file into your WCF Library, it will simply be ignored.
The client will not access the database, it will consume your service which is who accesses the database. Therefore, there is no need to declare the connectiong string in the client App.config.
I have a custom datatype I put in a class Library SharedTypes
namespace SharedTypes
{
public class District
{
public long Id { get; set; }
public string Name { get; set; }
}
}
I then have a WCF server with this service
using System.ServiceModel;
using SharedTypes;
namespace WCF.WCFInterfaces
{
[ServiceContract]
public interface IWcfService
{
[OperationContract]
District GetDistrict(long id);
[OperationContract]
void CreateDistrict(District district);
[OperationContract]
List<District> GetDistricts();
}
}
On the client side I have a Interface (So I inject the implementation)
using SharedTypes;
namespace WcfInterfaces
{
public interface IDistrictManager
{
void CreateDistrict(District district);
District GetDistrict(long id);
List<District> GetDistricts();
}
}
I finally have the implementation the client should use
public class DistrictManager : IDistrictManager
{
private readonly WcfServiceClient _salesService;
public DistrictManager()
{
_salesService = new WcfServiceClient();
}
public void CreateDistrict(District district)
{
_salesService.CreateDistrictAsync(district);
}
public District GetDistrict(long id)
{
return _salesService.GetDistrict(id);
}
public List<District> GetDistricts()
{
var list = _salesService.GetDistricts();
return list.ToList();
}
}
But here the problem arises, this implementation expects to use a version of District it gets from the service reference
WcfClientLibrary.SalesService.District
Instead of
SharedTypes.District
They are the same, but VS dont know that
So I get errors that the interface is not properly implemented because I have 2 different types of the District class.
How can I get the Service reference to use the SharedTypes.District instead? Or is it my way of implementing it that is way off?
Right click your service reference in client project and check "Reuse Types in Referenced Assemblies".
Be sure that you have added SharedTypes.District to your client service reference project.
When adding your WCF reference on the client side. Click on the advanced options.
There is a setting that you can specify to tell it to re-use types from specified assembly(s).
You'll be able to specify the assembly(s).
It looks like serverside cannot receive the passed values, requestVersion.Ping is empty.
namespace Communication
{
public class DataForRequestVersion
{
public string Ping = "";
}
public class DataForResponseVersion
{
public string Pong = "";
public string Version = "";
}
}
[ServiceContract]
public interface IService
{
[OperationContract]
Communication.DataForResponseVersion Version(Communication.DataForRequestVersion requestVersion);
}
//Server
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
public class ServiceImplementation : WCFSimple.Contract.IService
{
public Communication.DataForResponseVersion Version(Communication.DataForRequestVersion requestVersion)
{
//Here requestVersion.Ping is EMPTY
Communication.DataForResponseVersion responseVersion = new Communication.DataForResponseVersion();
responseVersion.Pong = requestVersion.Ping;
responseVersion.Version = "MyApp v" + Settings.version;
return responseVersion;
}
}
//Client makes a request here
Communication.DataForRequestVersion requestVersion = new Communication.DataForRequestVersion();
requestVersion.Ping = DateTime.Now.ToString(Settings.DayTimePreciseFormat);
//Here requestVersion.Ping has a value
Communication.DataForResponseVersion responseVersion =
Service.Version(requestVersion);
What am I missing?
UPDATE
My application works very well, both sides communicate by passing custom data classes without any problem. However I tried to modify test client which one only sends-receives current time as string and made its parameter a bit complex; from string to custom data class. Main solution's application can send Version request and receive the answer. So I think my little test client got a problem.
Here is the pastebin code:
2nd UPDATE:
Some moderator doesn't allow me to answer my own question, I don't know why, I found a very similar question and the guy answered his own too. To help others next time I'm explaining the reason; I used namespace instead of creating class...And I fixed:
//namespace Communication
public class Communication
You need to label your request (and response) classes with the [DataContract] attribute, and their properties with the [DataMember] attribute:
[DataContract]
public class DataForRequestVersion
{
[DataMember]
public string Ping = "";
}
try using [DataContract] on your Data...classes... and [DataMember] on their fields...
Change the fields in DataForRequestVersion DataForResponseVersion classes to properties. By Default DatacontractSerializer will serialize public properties.
I've got a class which looks a little like this....
[DataContract]
public partial class Area : ModelBase
{
private String name;
private Guid floorId;
private Guid areaTypeId;
private int assetCount;
[DataMember]
public String Name
{
get { return name; }
set { name = value; }
}
[DataMember]
public Guid FloorId
{
get { return floorId; }
set { floorId = value; }
}
public Guid AreaTypeId
{
get { return areaTypeId; }
set { areaTypeId = value; }
}
}
....and I have a Wcf Service Library which has the following interface defined...
IEnumerable<Area> GetSomeStuff(IEnumerable<Area> uploadedAreas);
It's all working just fine, but in my client app (a compact framework application) the AreaTypeId property is exposed?
I thought that if I didn't add the [DataMember] attribute it wouldn't be seen by the client? What am not understanding???
Thanks,
ETFairfax
If you want to hide any property from client then just add [IgnoreDataMember] attribute to that property.
If you are sharing type assembly between client and server It will be visible unless you turn off reusing types from referenced assemblies (click "Configure Service Reference" on proxy).
If you are not sharing assembly it will not be visible because code for class is generated based on exposed contract (you can see it by turning on Show All Files in VS and then go to generated file Reference.cs under service proxy).
DataMember is attribute for DataContractSerializer so if you are sharing assembly the property will be not serialized on server and not initialized on client but it will be visible. Reference