I have a wpf application which calls a wcf service method. The method runs fine in debugging mode but the method doesnt return back to the client call.
Here is the code.
Client:
public class Provider
{
private static ActionServiceClient Client { get; set; }
static Provider()
{
Client = new ActionServiceClient();
}
public UserResponse GetUsers(UserRequest request)
{
UserResponse resp = new UserResponse();
resp = Client.GetUsers(request);
return resp;
}
}
WCF Service :
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Reentrant, UseSynchronizationContext = false)]
public class ActionService : IActionService
{
public MovieResponse GetReviews(MovieRequest request)
{
List<MovieReview> reviews = DataAccess.GetMovieReviews(0);
MovieResponse response = new MovieResponse();
response.movieReviews = reviews;
return response;
}
public UserResponse GetUsers(UserRequest request)
{
List<User> users = DataAccess.GetUsers(0);
UserResponse resp = new UserResponse();
resp.users = users;
return resp;
}
[DataContract]
public class UserResponse
{
[DataMember]
public List<User> users;
}
[DataContract]
public class UserRequest
{
[DataMember]
public int userId;
}
I run the program in debug mode and after completion of the service call the wpf application hangs....
Oops....Passing an image is not allowed.
Related
I am trying to use the Ninject Dependency Injection to bind a callback method to WCF REST services runs in a kind of plugin module of a software system, which is NOT possible to use the SVC file or webconfig or app.config for any configuration.
The interface and implementation of the WCF services are defined as below:
[ServiceContract]
public interface IService1
{
[OperationContract]
[WebInvoke(Method = "GET", ResponseFormat = WebMessageFormat.Json, RequestFormat = WebMessageFormat.Json)]
string DoWork();
}
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
public class Service1 : IService1
{
private IEventCallback EventCallback { get; set; }
public Service1(IEventCallback eventCallback)
{
EventCallback = eventCallback;
}
public string DoWork()
{
if (EventCallback != null)
{
EventCallback.Send("Testing Event ID");
}
return "Success";
}
}
where the IEventCallback and the corresponding implementation are defined as below:
public interface IEventCallback
{
void Send(string eventId);
}
public class EventCallback : IEventCallback
{
private Action<string> OnSendCustomEventCallBack { get; set; }
public EventCallback(Action<string> onSendCustomEventCallBack)
{
OnSendCustomEventCallBack = onSendCustomEventCallBack;
}
public void Send(string eventId)
{
if (OnSendCustomEventCallBack != null)
{
OnSendCustomEventCallBack(eventId);
}
}
}
The codes to create the REST Service are as below:
public AuthenticatedWebServiceHost(Type type, Uri url, string authenUsername, string authenPassword)
{
AuthenUsername = authenUsername;
AuthenPassword = authenPassword;
IDictionary<string, ContractDescription> desc;
InitializeDescription(type, new UriSchemeKeyedCollection());
base.CreateDescription(out desc);
var val = desc.Values.First();
var binding = new WebHttpBinding();
binding.Security.Mode = WebHttpSecurityMode.TransportCredentialOnly;
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Basic;
Credentials.UserNameAuthentication.UserNamePasswordValidationMode = UserNamePasswordValidationMode.Custom;
Credentials.UserNameAuthentication.CustomUserNamePasswordValidator =
new CustomUserNamePasswordValidator(AuthenUsername, AuthenPassword);
AddServiceEndpoint(val.ContractType, binding, url);
}
And, the AuthenticatedWebServiceHost is called as below:
var eventCallback = new EventCallback(OnSendCustomEventCallBack); // where OnSendCustomEventCallBack is a defined method
// How to write codes to use Ninject to inject the callback into the Service?
// kernel.Bind<IEventCallback>().To<??>()
_webServiceHost = new AuthenticatedWebServiceHost(typeof(Service1), new Uri("http://localhost:9000/Events"),
"admin", "password");
_webServiceHost.Open();
Since, no XML configuration is allowed in my case, how to write codes to use Ninject to bind the callback to the WCF Services?
I eventually figured out the solution by referencing Is it possible to instantiate a WebServiceHost via an instance of the service type, without a parameterless constructor? without using NInject.
I have a self hosted WCF service for handling HTTP POST request.
My WCF service method will handle 2 types of request (1. getting data, 2. Do some action with given data).
My scenario :
1. Started Action request with large amount of data. : during the starting of that action do some processing.
2. client reads some results.
3. sending the remaining data for the previous action.
I implemented this using 'TcpListener' it is working.
Problem:
when i try to implement this scenario using WCF, i have got the 'Bad request' during the first action request.
[ServiceContract]
public interface ITest
{
[OperationContract, WebInvoke(Method = "POST", UriTemplate = "{*pathname}")]
Stream GetResponse(string pathname, Stream requestBody);
}
[ServiceBehavior(AddressFilterMode = AddressFilterMode.Exact, ConcurrencyMode = ConcurrencyMode.Single, InstanceContextMode = InstanceContextMode.Single, UseSynchronizationContext = false, IncludeExceptionDetailInFaults = true)]
class TestService : ITest
{
public Uri BaseUri { get; private set; }
public IPAddress Address { get; private set; }
public Int32 Port { get; private set; }
public bool IsStarted { get { return Host != null; } }
public ServiceHost Host { get; private set; }
public TestService()
{
}
public TestService(IPAddress ipAddress, int port)
{
if (ipAddress == null) { throw new ArgumentNullException("Address"); }
this.Address = ipAddress;
this.Port = port;
this.BaseUri = new Uri(string.Format("http://{0}:{1}", this.Address, this.Port));
}
public void Start()
{
if (IsStarted) { throw new InvalidOperationException("Service is already started."); }
Host = CreateServiceHost();
Host.Open();
}
public void Stop()
{
if (!IsStarted) { throw new InvalidOperationException("Service is already stopped."); }
Host.Close();
Host = null;
}
private ServiceHost CreateServiceHost()
{
ServiceHost host = new ServiceHost(typeof(TestService), this.BaseUri);
WebHttpBinding webhttpBinding = new WebHttpBinding();
webhttpBinding.MaxBufferPoolSize = int.MaxValue;
webhttpBinding.MaxBufferSize = int.MaxValue;
webhttpBinding.MaxReceivedMessageSize = int.MaxValue;
CustomBinding binding = new CustomBinding(webhttpBinding);
WebMessageEncodingBindingElement webEncoding = binding.Elements.Find<WebMessageEncodingBindingElement>();
webEncoding.ContentTypeMapper = new RawMapper();
host.AddServiceEndpoint(typeof(ITest), binding, new Uri(this.BaseUri.AbsoluteUri)).Behaviors.Add(new WebHttpBehavior());
return host;
}
public Stream GetResponse(string pathname, Stream requestBody)
{
Stream response=null;
/************** Process 'requestBody' **************/
//requestBody contains "MY_ACTION"
//{
// Find the start delimeter from response : START processing
// Find the end delimeter from response : STOP processing
//}
//requestBody contains "GET_MY_DATA"
//{
// Find data and send response
//}
return response;
}
}
public class RawMapper : WebContentTypeMapper
{
public override WebContentFormat GetMessageFormatForContentType(string contentType)
{
return WebContentFormat.Raw;
}
}
Any help/guidance would be great as I'm really stuck on this.
I have a wpf application which calls a wcf service method. The method runs fine in debugging mode but the method doesnt return back to the client call.
Here is the code.
Client:
public class Provider
{
private static ActionServiceClient Client { get; set; }
static Provider()
{
Client = new ActionServiceClient();
}
public UserResponse GetUsers(UserRequest request)
{
UserResponse resp = new UserResponse();
resp = Client.GetUsers(request);
return resp;
}
}
WCF Service :
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Reentrant, UseSynchronizationContext = false)]
public class ActionService : IActionService
{
public MovieResponse GetReviews(MovieRequest request)
{
List<MovieReview> reviews = DataAccess.GetMovieReviews(0);
MovieResponse response = new MovieResponse();
response.movieReviews = reviews;
return response;
}
public UserResponse GetUsers(UserRequest request)
{
List<User> users = DataAccess.GetUsers(0);
UserResponse resp = new UserResponse();
resp.users = users;
return resp;
}
[DataContract]
public class UserResponse
{
[DataMember]
public List<User> users;
}
[DataContract]
public class UserRequest
{
[DataMember]
public int userId;
}
I run the program in debug mode and after completion of the service call the wpf application hangs....
Oops....Passing an image is not allowed.
I have a WCF Windows Service that checks for MSMQ messages.
It picks the messages up ok but the ProcessMSMQMessage event does not seem to get called.
Any ideas why this is? Have I set ProcessMSMQMessage event correctly? Or am I missing something?
My code is below. Thanks.
WCF Service Class...
public partial class MyService : ServiceBase
{
private ServiceHost host;
public MyService()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
string queueName = ConfigurationManager.AppSettings["ProcessMsgQueueName"];
if (!MessageQueue.Exists(queueName))
{
MessageQueue thisQueue = MessageQueue.Create(queueName, true);
thisQueue.SetPermissions("Everyone", MessageQueueAccessRights.ReceiveMessage);
}
try
{
Uri serviceUri = new Uri("msmq.formatname:DIRECT=OS:" + queueName);
// communicate to MSMQ how to transfer and deliver the messages
MsmqIntegrationBinding serviceBinding = new MsmqIntegrationBinding();
serviceBinding.Security.Transport.MsmqAuthenticationMode = MsmqAuthenticationMode.None;
serviceBinding.Security.Transport.MsmqProtectionLevel = System.Net.Security.ProtectionLevel.None;
serviceBinding.SerializationFormat = MsmqMessageSerializationFormat.Binary;
host = new ServiceHost(typeof(MyService.Service1)); // add watcher class name
host.AddServiceEndpoint(typeof(MyService.IService1), serviceBinding, serviceUri);
host.Open();
}
catch (Exception ex)
{
EventLog.WriteEntry("SERVICE" + ex.Message, EventLogEntryType.Error);
}
}
protected override void OnStop()
{
if (host != null)
host.Close();
}
}
IService1 Contract...
[ServiceContract(Namespace = "MyService")]
[ServiceKnownType(typeof(Events.Dashboard_Message))]
public interface IService1
{
[OperationContract(IsOneWay = true)]
void ProcessMSMQMessage(MsmqMessage<Events.Dashboard_Message> msg);
}
Service1 Class...
public class Service1 : IService1
{
[OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = true)]
public void ProcessMSMQMessage(MsmqMessage<Events.Dashboard_Message> msg)
{
string msgName = msg.GetType().Name;
// send to eventlog
EventLog.WriteEntry("MyService", msgName);
}
}
Got it working finally.
The issue was in IService1 contract. Needed to add Action = "*".
[OperationContract(IsOneWay = true, Action = "*")]
I have the following types:
public enum MyEnum
{
Value1,
Value2
}
[DataContract]
public class Configuration
{
[DataMember]
public MyEnum MyValue { get; set; }
[DataMember]
public Credentials CredentialValues { get; set; }
}
[DataContract, KnownType(typeof(CustomCredentials))]
public class Credentials
{
}
[DataContract]
public class CustomCredentials : Credentials
{
[DataMember]
public string Property1 { get; set; }
[DataMember]
public string Property2 { get; set; }
}
And on my service interface, I have a function that returns an instance of Configuration with its CredentialValues property set to a fully populated instance of CustomCredentials. I receive no errors from the client or the server, but while the data is being property serialized on the server and received by the client, the properties on CustomCredentials never have a value. What do I need to change here in order to have these properties properly deserialized on the client?
For reference, the connection between client and server is made with a DuplexChannelFactory over a NetTcpBinding using a data/service contract project that is shared by the client and service applications (the service is self-hosted), so there are no service proxy types that could need to be regenerated.
Added this code to the Contracts project along with your DataContracts.
[ServiceContract(Namespace = "http://schemas.platinumray.com/duplex", SessionMode = SessionMode.Required, CallbackContract = typeof(IService1Callback))]
public interface IService1
{
[OperationContract(IsOneWay = true)]
void GetData();
}
public interface IService1Callback
{
[OperationContract(IsOneWay = true)]
void SetData(Configuration config);
}
Created the service.
public class Service1 : IService1
{
public void GetData()
{
var x = new Configuration()
{
MyValue = MyEnum.Value1,
CredentialValues = new CustomCredentials { Property1 = "Something", Property2 = "Something else" }
};
OperationContext.Current.GetCallbackChannel<IService1Callback>().SetData(x);
}
}
class Program
{
static void Main(string[] args)
{
using (ServiceHost host = new ServiceHost( typeof(Service1), new Uri[] { new Uri("net.tcp://localhost:6789") }))
{
host.AddServiceEndpoint(typeof(IService1), new NetTcpBinding(), "Service1");
host.Open();
Console.ReadLine();
host.Close();
}
}
}
Created the client.
public class CallbackHandler : IService1Callback
{
public void SetData(Configuration config)
{
Console.WriteLine(config.CredentialValues.GetType().Name);
Console.WriteLine(((CustomCredentials)config.CredentialValues).Property1);
Console.WriteLine(((CustomCredentials)config.CredentialValues).Property2);
}
}
class Program
{
static void Main(string[] args)
{
// Setup the client
var callbacks = new CallbackHandler();
var endpoint = new EndpointAddress(new Uri("net.tcp://localhost:6789/Service1"));
using (var factory = new DuplexChannelFactory<IService1>(callbacks, new NetTcpBinding(), endpoint))
{
var client = factory.CreateChannel();
client.GetData();
Console.ReadLine();
factory.Close();
}
}
}
Outputs the following as expected:
CustomCredentials
Something
Something else
So this actually worked without modifying any of your data contracts... The same results if I revert to a twoway operation and just return Configuration directly without using the callback.
Also tried making Credentials abstract but could not replicate your problem.
Have I missed something?