I have this strange problem where my client will hang when it calls a method from my WCF Service. Now the real strange thing is that this does not happen when the Client is a Console Application. It does happen when the client is a WinForm or WPF application.
I created a Client Library that a WCF Client can use to connect to the Service, seen here:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel; //needed for WCF communication
namespace DCC_Client
{
public class DCCClient
{
private DuplexChannelFactory<ServiceReference1.IDCCService> dualFactory;
public ServiceReference1.IDCCService Proxy;
public DCCClient()
{
//Setup the duplex channel to the service...
NetNamedPipeBinding binding = new NetNamedPipeBinding();
dualFactory = new DuplexChannelFactory<ServiceReference1.IDCCService>(new Callbacks(), binding, new EndpointAddress("net.pipe://localhost/DCCService"));
}
public void Open()
{
Proxy = dualFactory.CreateChannel();
}
public void Close()
{
dualFactory.Close();
}
}
public class Callbacks : ServiceReference1.IDCCServiceCallback
{
void ServiceReference1.IDCCServiceCallback.OnCallback(string id, string message, Guid key)
{
Console.WriteLine(string.Format("{0}: {1}", id, message));
}
}
}
Here is the code for the working WCF Console Client:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DCC_Client;
namespace Client_Console_Test
{
class Program
{
private static DCCClient DCCClient;
static void Main(string[] args)
{
try
{
DCCClient = new DCCClient();
DCCClient.Open();
DCCClient.Proxy.DCCInitialize(); //returns fine from here
Console.ReadLine();
DCCClient.Proxy.DCCUninitialize();
DCCClient.Close();
}
catch (Exception e)
{
throw;
}
}
}
}
And here is the code for the WPF Client that freezes (see comment)
using System; //etc
using DCC_Client; //Used for connection to DCC Service
namespace Client_WPF_Test
{
public partial class Main : Window
{
private static DCCClient DCCClient;
public Main()
{
InitializeComponent();
DCCClient = new DCCClient();
DCCClient.Open();
}
private void Connect_btn_event() {
try
{
DCCClient.Proxy.DCCInitialize(); //**never returns from this**
}
catch (Exception e)
{
MessageBox.Show(e.Message);
}
}
I stepped into the code DCCClient.Proxy.DCCInitialize(); and the service executes the commands successfully, however, for some reason the client gets stuck here and does not continue executing. The client gives no exception, and the stack trace says [external code].
That being said, the Console Client runs perfectly. I think I am missing something simple here. I appreciate any help you can provide.
In case that your service call backs the client directly from DCCInitialize and both operation and callback operation are not marked as one-way your application will deadlock. Try marking your callback implementation with this attribute:
[CallbackBehavior(ConcurrencyMode=ConcurrencyModel.Reentrant)]
Instead of this you can also try to mark operations in both contracts with
[OperationContract(IsOneWay=true)]
But both operations must return void
For the last if neither of these helps try to mark your callback implementation with:
[CallbackBehavior(UseSynchronizationContext=false)]
but in this case your callback operation will run in another thread and it will not be able to manipulate with UI controls directly.
Edit:
WCF behaves differently when hosted in UI thread. In such scenario all request are processed in sequential order in standard windows message loop so if you call the service you blocked your current thread but the service calls back your client and it waits to process the message but it can't because thread is blocked by the initial call = deadlock until initial request timenouts. By using last mentioned behavior you will say WCF to not join windows message loop and instead process messages in separate threads as usual. There is no security issue with this except the fact that you cannot access UI control from methods running in other threads - both WinForms and WPF has approaches to pass commands from other thread.
Related
I have an asp.net core application hosted and webdav enabled in IIS for storing files as well. I want to know when a user saves a file in the webdav server (ie, if opened and saved in Microsoft word). I have put together this IIS module to try and intercept all http requests so I can find out what a webdav HTTP requests look like and then hopefully create a if statement using this logic once I can identify the save request. So far here is the IIS module I have created:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web;
namespace WebDAVTargetDetectorIIS
{
public class LoggingModule : IHttpModule
{
#region IHttpModule Members
public void Dispose()
{
}
public void Init(HttpApplication context)
{
context.PreRequestHandlerExecute += new EventHandler(OnPreRequestHandlerExecute);
context.PostLogRequest += new EventHandler(PostLogEvent);
}
#endregion
public void OnPreRequestHandlerExecute(Object source, EventArgs e)
{
HttpApplication app = (HttpApplication)source;
HttpRequest request = app.Context.Request;
if (!String.IsNullOrEmpty(request["HTTP_CF_CONNECTING_IP"]))
{
request.ServerVariables.Set("REMOTE_ADDR", request["HTTP_CF_CONNECTING_IP"]);
}
}
public void PostLogEvent(Object source, EventArgs e)
{
HttpApplication app = (HttpApplication)source;
HttpRequest request = app.Context.Request;
app.Response.AppendToLog("This is a test");
}
}
}
I have created the BIN folder in the root folder of my web application and used the IIS Manager to add the new module. It is added to the end of the ordered list. The log files in IIS seem to save to "C:\inetpub\logs\LogFiles\W3SVC1" however my module does not seem to be printing my test line in there. Is there a particular reason the code above would not implement on any even a login request? Or should I be attaching this to some other event?
I am trying to use the BackgroundService is an asp.net core 2.2 project using the Razor page project template, not MVC. This little sample app took me about 1 minute to write so it couldn't be much simpler. Looking at the debugger I know the background service is starting and chugging along just fine. But when I attempt to navigate to a page (path 'Banana') that requires this service as a dependency, I get InvalidOperationException: Unable to resolve service for type 'WebApplication23.DumbService' while attempting to activate 'WebApplication23.Pages.BananaModel'. Why can't I access this service from my page model? The code is at https://github.com/jmagaram/SimpleBackgroundService
I have the following service:
using Microsoft.Extensions.Hosting;
using System.Threading;
using System.Threading.Tasks;
namespace WebApplication23
{
public class DumbService : BackgroundService
{
public DumbService()
{
}
public void QueueWork()
{
}
protected async override Task ExecuteAsync(CancellationToken cancellationToken)
{
while (!cancellationToken.IsCancellationRequested) {
await Task.Delay(TimeSpan.FromSeconds(1));
}
}
}
}
And this is where I register it:
services.AddHostedService<DumbService>();
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
Here is a page model that uses it:
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
namespace WebApplication23.Pages
{
public class BananaModel : PageModel
{
private readonly DumbService _service;
public BananaModel(DumbService service)
{
_service = service;
}
public void OnGet()
{
}
}
}
Registering a background service doesn't actually add it to the service collection, mostly because there's no need to. The whole point of a background service is that your app doesn't really need to know about it. It's not clear why you think you need this service injected, but almost certainly you'd be better served by factoring out whatever logic you need in your Razor Page into a separate class that both the service and your Razor page can utilize.
UPDATE
See the documentation on IHostedService where an example of a queue background service is given. You'll notice that the actual hosted service is injected with the task queue. Your app then would also inject just the task queue itself to schedule tasks.
I am trying to use the JAX-RS Client API to request a resource through HTTP GET, by using the following code: (I used jersey-client v2.12 and also resteasy-client v3.0.8.Final to test the implementation)
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.InvocationCallback;
public class StackOverflowExample {
public static void main(String[] args) {
Client client = ClientBuilder.newClient();
client.target("http://example.com/").request().async().get(new InvocationCallback<String>() {
#Override
public void completed(String s) {
System.out.println("Async got: " + s);
}
#Override
public void failed(Throwable throwable) {
System.out.println("Async failure...");
}
});
}
}
As I expected the String is printed almost immediately. But the process keeps running about one minute, although there isn't any code that should be executed.
The JAX-RS spec just says that we should use the InvocationCallback and nothing else that matters to my issue. But even if I use a Future the same effect happens. I also tested, if this has something to do with a timeout, which was very unlikely and wrong. The debugger shows that there are some threads running namely DestroyJavaVM and jersey-client-async-executor-0 or pool-1-thread-1 in the case of resteasy.
Do you have any idea what is going wrong here?
It is allways helpful to consult the JavaDoc. Concerning my issue it says:
Clients are heavy-weight objects that manage the client-side communication infrastructure. Initialization as well as disposal of a Client instance may be a rather expensive operation. It is therefore advised to construct only a small number of Client instances in the application. Client instances must be properly closed before being disposed to avoid leaking resources.
If I close the client properly everything is working as expected.
public class StackOverflowExample {
public static void main(String[] args) {
Client client = ClientBuilder.newClient();
// request here
client.close();
}
}
I'm in the process of converting an ASP.NET MVC3 (LinqToSQL, EntityFramework) project to MVC4. I've created a fresh MVC4 project in VS2012, added packages, copied my Views, Controllers, etc.
Most things seem to work fine except when I try to access a controller that makes use of a Respository, as follows:
public class CustomerController : Controller
{
private ICustomerRepository _cr;
public CustomerController()
{
this._cr = new CustomerRepository(TTDataProvider.DB);
}
public CustomerController(ICustomerRepository customerRepository)
{
this._cr = customerRepository;
}
if I'm in VS2012 and debugging, what I'll get is an exception: "Activation error occured while trying to get instance of type CustomerController, key """. The exception is of type Microsoft.Practices.ServiceLocation.Activation and the Inner Exception is: "StructureMap Exception Code: 202\nNo Default Instance defined for PluginFamily TTLW.Models.TTLWDataContext, TTLW, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"}.
My IoC code is:
using StructureMap;
using FluentSecurity;
using System.Diagnostics;
namespace TTLW {
public static class IoC {
public static IContainer Initialize() {
ObjectFactory.Initialize(x =>
{
x.Scan(scan =>
{
scan.TheCallingAssembly();
scan.WithDefaultConventions();
scan.AddAllTypesOf<IPolicyViolationHandler>();
});
});
return ObjectFactory.Container;
}
}
}
And here's StructureMapMVC.cs
using System.Web.Http;
using System.Web.Mvc;
using StructureMap;
using TTLW.DependencyResolution;
[assembly: WebActivator.PreApplicationStartMethod(typeof(TTLW.App_Start.StructuremapMvc), "Start")]
namespace TTLW.App_Start {
public static class StructuremapMvc {
public static void Start() {
IContainer container = IoC.Initialize();
DependencyResolver.SetResolver(new StructureMapDependencyResolver(container));
GlobalConfiguration.Configuration.DependencyResolver = DependencyResolver.Current.ToServiceResolver();
}
}
}
As I say, this was all working without problems in my MVC3 application (although I was of course using the MVC3 version of StructureMap).
Once I hit the exception, if I just choose to continue then everything works (i.e. the controller functions); this is confirmed by choosing "Start Without Debugging" instead of "Debug". When I do that there is no exception thrown and things work as designed.
I've searched and come across posts from Phil Haack, Brett Allred and others (in fact I've already incorporated Allred's code in the last line of StructureMapMVC) but haven't found a solution. I can't consider the project converted as long as this exception is staring me in the face.
I've included all the code and messages I think are reasonable and would appreciate any insights. If you need to see more just let me know.
Thanks in advance.
I'm developing a WPF desktop application with caliburn.micro framework, and I want to configure ninject interceptors so that I can intercept method calls. I would like to do this to handle exceptions in a centralized place, so that I don't have many try-catch blocks everywhere around my code.
I haven't been able to acomplish this, because everytime I wire everything up with ninject, the system throws an exception.
So here's some code:
The AppBootstrapper configure method looks like this:
protected override void Configure()
{
_kernel = new StandardKernel(new NinjectServiceModule());
_kernel.Bind<IWindowManager>().To<WindowManager>().InSingletonScope();
_kernel.Bind<IEventAggregator>().To<EventAggregator>().InSingletonScope();
_kernel.Bind<ISomeViewModel>().To<SomeViewModel>().Intercept().With<SomeInterceptor>() //this is where the exception is thrown;
_kernel.Bind<IShell>().To<ShellViewModel>();
}
Now the intercept method in my interceptor:
public void Intercept(IInvocation invocation)
{
if (invocation.Request.Method.Name == "TheMethodIWantIntercepted")
{
try
{
invocation.Proceed();
}
catch (Exception)
{
Console.WriteLine("I Handled exception");
}
}
else
{
invocation.Proceed();
}
}
The method in the view model looks like this:
public virtual void TheMethodIWantIntercepted()
{
//Some logic here
}
So that's how interceptors are supposed to work. But it doesn't work, everytime I run the program, and ninject tries to inject the instance of SomeViewModel into ISomeViewModel, the program execution fails, and this is the exception that is thrown (and the stack trace):
http://pastebin.com/qerZAjVr
Hope you can help me with this, thank you in advance.
You have to load either DynamicProxy(2)Module or LinFuModule depending on what proxy library you prefer.
Also be aware that Ninject 2.2 will create a class proxy for SomeViewModel which requires:
a parameterless constructor
virtual methods
Interface proxies don't have this restriction but this requires Ninject 3.0.0