Nancy 503 Errors switching to OWIN self host - authentication

I have some webservices currently hosted with Nancy.Hosting.Self
I need to move the services from Nancy.Hosting.Self to being hosted with Microsoft.Owin.SelfHost so that I can use OWIN for user authentication.
Theoretically, I should be able to simply replace my NancySelfHost class with an Owin Startup class. However, when run the service with my Owin Startup class, Nancy returns: "HTTP Error 503. The service is unavailable."
I am currently swapping the hosting class based on build parameters. (They are launched via TopShelf)
Launcher:
#define OWIN
using Topshelf;
namespace BasisRESTApi
{
public class Program
{
private static readonly string _serviceName = "MyRestApi";
private static readonly string _displayName = "My REST services";
private static readonly string _description = "Minor RESTful web services for interop.";
public static void Main()
{
HostFactory.Run(x =>
{
x.UseLinuxIfAvailable();
// Automate recovery
x.EnableServiceRecovery(recover =>
{
recover.RestartService(0);
});
#if OWIN
x.Service<Startup>(s =>
{
s.ConstructUsing(name => new Startup(_serviceName));
#else
x.Service<NancySelfHost>(s =>
{
s.ConstructUsing(name => new NancySelfHost());
#endif
s.WhenStarted(tc => tc.Start());
s.WhenStopped(tc => tc.Stop());
});
x.StartAutomatically();
x.RunAsLocalSystem();
x.SetDescription(_description);
x.SetDisplayName(_displayName);
x.SetServiceName(_serviceName);
});
}
}
}
NancySelfHost: (Works)
using System;
using System.Configuration;
using System.Net;
using System.Text.RegularExpressions;
using System.Threading;
using Logging;
using Nancy.Hosting.Self;
using static Logging.Logging;
namespace BasisRESTApi
{
public class NancySelfHost
{
private NancyHost _nancyHost;
public void Start()
{
var hostUrl = "https://localhost:2020";
_nancyHost = new NancyHost(new Uri(hostUrl));
_nancyHost.Start();
}
public void Stop()
{
_nancyHost.Stop();
}
}
}
Owin Startup: (Runs but returns 503 Errors)
using Logging;
using Microsoft.Owin;
using Microsoft.Owin.Hosting;
using Owin;
using System;
using System.Configuration;
using System.Net;
using System.Text.RegularExpressions;
using System.Web.Http;
using static Logging.Logging;
[assembly: OwinStartup(typeof(BasisRESTApi.Startup))]
namespace BasisRESTApi
{
public class Startup
{
public string ServiceName { get; set; }
private static IDisposable _application;
public Startup(string serviceName)
{
ServiceName = serviceName;
}
public void Start()
{
var hostUrl = "https://localhost:2020";
_application = WebApp.Start<Startup>(hostUrl);
}
public void Stop()
{
_application?.Dispose();
}
public void Configuration(IAppBuilder application)
{
UseWebApi(application);
application.UseErrorPage();
var listener = (HttpListener)application.Properties["System.Net.HttpListener"];
// Different authentication methods can be specified for the webserver here
listener.AuthenticationSchemes = AuthenticationSchemes.Negotiate;
//NOTE:All of the above can be removed and the issue is not impacted.
application.UseNancy();
}
/// <summary>
/// Provide API Action
/// </summary>
/// <param name="application"></param>
private static void UseWebApi(IAppBuilder application)
{
var config = new HttpConfiguration();
config.MapHttpAttributeRoutes();
application.UseWebApi(config);
}
}
}
Other notes:
UrlAcls and SslCerts are properly set to work for this port, as evidenced by it working with NancySelfHost.
I do not have duplicate urlacl entries as per 503 Error when using NancyFx with Owin
I have tried ports higher than :5000 and it did not help
The same issues occur when run through visual studio as an administrator, or run from the console as an administrator. (Annoyingly, OWIN seems to require admin rights to self-host)
The 503 is generated prior to any of the handler code being run. (IOW, breakpoints at the entry of the webservice code are not hit.)

I discovered the answer here
Essentially, the urlacl that is required for Nancy self-host is not needed for OWIN self hosting, and in fact causes the 503 errors if it is not deleted. (Apparently OWIN uses some other mechanism to get rights to the port -- probably the reason why OWIN requires admin rights to run the .exe or to debug the .exe in Visual Studio)
Running the following resolved the issue:
netsh http delete urlacl url=https://+:2020/

Related

NinjectServiceHost in WCF service does not call Dispose()

I've been trying to get the Dispose method on my IDisposable WCF service called whilst using Ninject's NinjectServiceHost without any luck. I've then downloaded the Ninject.extensions.WCF example code and tried to get the IDisposable TimeService's Dispose() method to be called, but it does not get called either.
The service is instantiated correctly, just the Dispose() doesn't get called.
Is this a bug or something that myself and the example code are missing?
I've created a stripped down service and testing host that reproduces the issue. The code is below.
I'm using Ninject 3.0.1.10, Ninject.extensions.WCF 3.0.0.5, .net 4.5
ServiceModule.cs code (for setting up bindings)
using Ninject.Modules;
namespace TestNinjectWcf
{
public class ServiceModule : NinjectModule
{
public override void Load()
{
Bind<Service1>().ToSelf();
// I've also tried Bind<IService1>().To<Service1>()
// and also tried various scopes such as InParent() and InRequestScope()
}
}
}
Console Test Program to start the service.
using System;
using Ninject.Extensions.Wcf;
using Ninject;
using TestNinjectWcf;
namespace TestConsole
{
class Program
{
static void Main(string[] args)
{
var kernel = new StandardKernel(new ServiceModule());
var service = kernel.Get<NinjectServiceHost<Service1>>();
service.Open();
Console.WriteLine("Service Started");
Console.ReadKey();
service.Close();
}
}
}
Service Implementation
using System;
using System.Diagnostics;
using System.ServiceModel;
namespace TestNinjectWcf
{
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Multiple)]
public class Service1 : IService1, IDisposable
{
public Service1()
{
Debug.WriteLine("Constructor");
}
public string GetData(int value)
{
return string.Format("You entered: {0}", value);
}
public void Dispose()
{
Debug.WriteLine("Dispose"); // This line never gets called!
}
}
}
Maybe it is that you have created singleton service ? (InstanceContextMode.Single)
Only one InstanceContext object is used for all incoming calls and is not recycled subsequent to the calls. If a service object does not exist, one is created

SignalR Dependency Resolver not working from Javascript Hubs

I've recently upgraded to the new version of the excellent SignalR library, and moved all my Dependency Injection from StructureMap to Ninject, as Ninject seemed to be better supported.
I've got the dependency injection working fine for Server-side notifications using the "Broadcasting over a Hub from outside of a Hub" described here: https://github.com/SignalR/SignalR/wiki/Hubs.
The problem I'm getting is that all SignalR messages originating from the Javascript hub don't seem to be triggering the dependency injection.
I'm also using MVC4 WebAPI which also takes some shoe-horning to get dependency injection working.
Here's my Hub:
public class PresenceHub : Hub, IPresenceHub
{
private readonly IUserRepository _userRepository;
private readonly IFormsAuthenticationProvider _formsAuthenticationProvider;
public PresenceHub(IFormsAuthenticationProvider formsAuthenticationProvider, IUserRepository userRepository)
{
_userRepository = userRepository;
_formsAuthenticationProvider = formsAuthenticationProvider;
}
public void PresenceChange(string presence)
{
var user = _userRepository.FindById(_formsAuthenticationProvider.GetUserId());
var rosterEntry = Mapper.Map<User, RosterEntryDto>(user);
rosterEntry.Presence = presence;
Clients.updatePresence(rosterEntry);
}
}
Here's my Ninject Bootstrapper:
Namespace SLx.Web.App_Start
{
using System;
using System.Web;
using Microsoft.Web.Infrastructure.DynamicModuleHelper;
using Ninject;
using Ninject.Web.Common;
public static class NinjectWebCommon
{
private static readonly Bootstrapper bootstrapper = new Bootstrapper();
public static void Start()
{
DynamicModuleUtility.RegisterModule(typeof(OnePerRequestHttpModule));
DynamicModuleUtility.RegisterModule(typeof(NinjectHttpModule));
bootstrapper.Initialize(CreateKernel);
}
public static void Stop()
{
bootstrapper.ShutDown();
}
private static IKernel CreateKernel()
{
var kernel = new StandardKernel();
kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();
// SignalR Ninject Resolver
GlobalHost.DependencyResolver = new SignalR.Ninject.NinjectDependencyResolver(kernel);
// WebApi Ninject Resolver
GlobalConfiguration.Configuration.DependencyResolver = new NinjectDependencyResolver(kernel);
RegisterServices(kernel);
return kernel;
}
private static void RegisterServices(IKernel kernel)
{
}
}
I'm notifying clients on the serverside via a PresenceProxy defined as follows:
public class PresenceHubProxy : IPresenceHubProxy
{
private readonly IHubContext _hubContext;
public PresenceHubProxy()
{
_hubContext = GlobalHost.ConnectionManager.GetHubContext<PresenceHub>();
}
public void NotifyLogin(RosterEntryDto user)
{
_hubContext.Clients.updatePresence(user);
}
public void NotifyLogout(RosterEntryDto user)
{
_hubContext.Clients.updatePresence(user);
}
}
The Proxy works fine, injected into Controllers or their dependencies, and can send messages to the clients.
When the clients try to call SignalR via Javascript I get the following error:
No parameterless constructor defined for this object.
It looks like Ninject is not being invoked because the dependencies are not being injected into the constructor. What do I need to do to get Dependency Injection working for Javascript calls too?
Update --
Following advice from DFowler, I've replaced the Resolver in PostApplicationStart. Debugging I can see in the Immediate Window that SignalR.GlobalHost.Resolver is of type NinjectDependencyResolver but its still not working I get the same error - no paramaterless constructor.
I've then removed the NinjectDependencyResolver NuGet Library and added the source file to my solution and am using that for debugging purposes. Debugging on GetService and GetServices shows that neither method is ever called in NinjectDependencyResolver.
Any Ideas?
Problem was I hadn't called RouteTable.Routes.MapHubs:
GlobalHost.DependencyResolver = new SignalRNinjectResolver(NinjectWebCommon.Kernel);
RouteTable.Routes.MapHubs(new SignalRNinjectResolver(NinjectWebCommon.Kernel));
From the docs https://github.com/SignalR/SignalR/wiki/Extensibility:
NOTE: DO NOT override the global resolver in PreApplicationStart, it will not work, or it'll work only sometimes. Do it in PostApplicationStart (using WebActivator) or in Global.asax.

How do I program my WCF service in the given scenario?

I am currently developing a C# Windows Form Application that I intend to let it interact with a server. The server will receive posting from a mobile application that I have developed and whenever a posting is received, my Windows Form Application should be notified and give me a notification.
E.g. My mobile application sends an message over to my server. Once my server receives the message, my windows form application should display a new notification showing the content of the message received.
I am now starting to develop the WCF service and has reach the PostingService method and I am unsure of how I am able to continue to program the service to work the way I wan as stated above.
public class PostingService : IPostingService
{
public void NotifyAboutPosting(Posting post)
{
// do something with post here
}
}
and after I program the service, how do I test the service by, I dunno? uploading a fake post to see if the services works or whatsoever , meaning a dummy test. thanks !
EDIT
for my main method, the code are as follows ,
Uri baseAddress = new Uri("http://localhost/");
ServiceHost selfHost = new ServiceHost(typeof(IPostingService), baseAddress);
try
{
selfHost.AddServiceEndpoint(typeof(IPostingService),new WSHttpBinding(), "Posting");
ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
smb.HttpGetEnabled = true;
selfHost.Description.Behaviors.Add(smb);
selfHost.Open();
Console.WriteLine("The service is ready.");
Console.WriteLine("Press <ENTER> to terminate service.");
Console.WriteLine();
Console.ReadLine();
selfHost.Close();
}
catch (CommunicationException ce)
{
Console.WriteLine("An exception occurred: {0}", ce.Message);
selfHost.Abort();
}
basically I just followed through the tutorial given by MSDN WCF getting started tutorial. not sure if this is really the correct way to do it for the type of implementation that I want.
Well, your WCF service can do anything you want - so what do you really want it to do??
Your posting server gets a new message from a mobile device, and then calls this WCF service class in your Winforms app. What do you want to happen here and now??
One thing to keep in mind: the WCF service class receiving the message and the Winforms app might be running on different threads; if that's the case, you cannot just update e.g. UI elements on your Winforms UI from the service code (you need to use some synchronization methods). But that depends on your exact way of creating and opening the ServiceHost in your Winforms app.
Update: if you put your code to create and initialize your ServiceHost into the main application form (see Service Synchronization Context on CodeIdol for a sample on how to do this), then you could probably just do:
public class PostingService : IPostingService
{
public void NotifyAboutPosting(Posting post)
{
MessageBox.Show(post.Title, post.Message,
MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
assuming your Posting class has both a .Title and a .Message string property...
1) PostingService assembly (class-library project)
Interface: IPostingService.cs
using System;
using System.ServiceModel;
namespace PostingService
{
[ServiceContract]
public interface IPostingService
{
[OperationContract]
void NotifyAboutPosting(Posting posting);
}
}
Implementation: PostingService.cs
using System;
using System.Windows.Forms;
namespace PostingService
{
public class PostingService : IPostingService
{
public void NotifyAboutPosting(Posting posting)
{
MessageBox.Show(posting.Message, posting.Title, MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
}
DataContract: Posting.cs
using System;
using System.Runtime.Serialization;
namespace PostingService
{
[DataContract]
public class Posting
{
[DataMember]
public int ID { get; set; }
[DataMember]
public string Title { get; set; }
[DataMember]
public string Message { get; set; }
}
}
2) Your Winforms app (Winforms application project)
Must reference the service assembly (since it needs the service contract and the data contract class)
Main Form of your app: Form1.cs
using System;
using System.ServiceModel;
using System.ServiceModel.Description;
using System.Windows.Forms;
using PostingService; // your class library from above
namespace WinformsApp
{
public partial class Form1 : Form
{
private ServiceHost _host = null;
public Form1()
{
InitializeComponent();
// IMPORTANT: here you need the **SERVICE IMPLEMENTATION CLASS** in the typeof() (*NOT* the interface!)
_host = new ServiceHost(typeof(PostingService), new Uri("http://localhost:8888/PostingService"));
ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
smb.HttpGetEnabled = true;
_host.Description.Behaviors.Add(smb);
_host.Open();
label2.Text = "Service up and running (http://localhost:8888/PostingService)";
}
protected override void OnFormClosed(FormClosedEventArgs e)
{
_host.Close();
base.OnFormClosed(e);
}
}
}
3) Run your Winforms app - now that service is up and running and ready to be notified.
4) Launch WCF Test Client (that's what your "posting server" will be doing later on)
4a) File > Add Service - type in http://localhost:8888/PostingService - should find your service
4b) if found: enter some values into the properties for the "Posting" class (an ID, title, message)
4c) Click "Invoke" - your service should now be called, a dialog pop (message box) should pop up with the title and message you've defined
Perhaps WCF callbacks might meet your requirements:
What You Need To Know About One-Way Calls, Callbacks, And Events

SilverLight Enabled Wcf Service - can't keep track of session

I'm new to Silverlight and WCF services. I'm trying to write a client application that can manipulate an object server side.
My problem is that each time my Silverlight client makes a call to the service, it enters into the constructor systematically
public SilverLightEnabledWcfService()
{
}
In the below example, I simply want to increment or decrement a number depending on the activity client side.
How am I supposed to do this properly?
I also tried to create a regular ASP.net client page and I got the same result, ie the server doesn't remember the session. So I don't think the problem is in my client, but I'm still happy to post the code if it helps.
Thanks !!
using System;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Activation;
using Count.Library;
namespace Count.WebApp
{
[ServiceContract(Namespace = "")]
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]
public class SilverLightEnabledWcfService
{
public SilverLightEnabledWcfService()
{
}
private Class1 _class1;
[OperationContract]
public int Add1()
{
if (_class1 == null)
_class1 = new Class1(0);
_class1.Add1();
return Value;
}
[OperationContract]
public int Remove1()
{
if (_class1 == null)
_class1 = new Class1(0);
_class1.Remove1();
return Value;
}
public int Value
{
get
{
return _class1.Count;
}
}
}
}
Sessions require the wsHttpBinding, but this is not supported by Silverlight. There are workarounds, though:
http://web-snippets.blogspot.com/2008_08_01_archive.html
http://forums.silverlight.net/forums/t/14130.aspx

Can you host multiple WCF processes in a single windows service?

I have a WCF process hosted in a windows service.
I am wondering if I can safely have multiple WCF processes that do different things hosted in the same windows service.
Do I have to worry about ports?
I am using a mex endpoint
EDIT: SO seems to be trimming my lengthy code/config example so there's a complete explanation here: http://thegrenade.blogspot.com/2009/08/hosting-multiple-wcf-services-under.html
Here's an example that may help get you going:
class Program {
static void Main() {
if (Environment.UserInteractive) {
ServiceManager serviceManager = new ServiceManager();
serviceManager.OpenAll();
Console.ReadKey();
serviceManager.CloseAll();
}
else
ServiceBase.Run(new WindowsService());
}
}
public class WindowsService : ServiceBase
{
public static string WindowsServiceName = "Windows Service Name";
public static string WindowsServiceDescription = "Windows Service Description";
public static string WindowsServiceUsername = #".\username";
public static string WindowsServicePassword = "password";
private readonly ServiceManager serviceManager = new ServiceManager();
private readonly IContainer components = new Container();
protected override void Dispose(bool disposing) {
if (serviceManager != null) serviceManager.CloseAll();
if (disposing && (components != null)) components.Dispose();
base.Dispose(disposing);
}
public WindowsService() {
ServiceName = WindowsServiceName;
CanStop = true;
}
protected override void OnStart(string[] args) {
base.OnStart(args);
serviceManager.OpenAll();
}
protected override void OnStop() {
serviceManager.CloseAll();
base.OnStop();
}
}
public class ServiceManager {
readonly List<ServiceHost> serviceHosts = new List<ServiceHost>();
public void OpenAll() {
OpenHost<Service1>();
OpenHost<Service2>();
...
}
public void CloseAll() {
foreach (ServiceHost serviceHost in serviceHosts)
serviceHost.Close();
}
private void OpenHost<T>() {
Type type = typeof(T);
ServiceHost serviceHost = new ServiceHost(type);
serviceHost.Open();
serviceHosts.Add(serviceHost);
}
}
/// <remarks>
/// Enables application to be installed as a Windows Service by running InstallUtil
/// </remarks>
[RunInstaller(true)]
public class WcfServiceHostInstaller : Installer {
public WcfServiceHostInstaller() {
Installers.Add(new ServiceInstaller
{
StartType = ServiceStartMode.Automatic,
ServiceName = WindowsService.WindowsServiceName,
Description = WindowsService.WindowsServiceDescription
});
Installers.Add(new ServiceProcessInstaller { Account = ServiceAccount.User, Username = WindowsService.WindowsServiceUsername, Password = WindowsService.WindowsServicePassword });
}
}
And some configuration
Here, the binding & behaviour configuration is shared across services but you may need different configurations for different types of services.
I use different ports for different services, but you don't have to.
...
Yes, you can. I am doing this exact thing in my project, hosting three separate WCF services inside my Windows service. Just make sure that each WCF endpoint, i.e., the address/binding/contract tuple, is unique.
Have a look at this Run WCF ServiceHost with multiple contracts its not exactly what you are asking for but maybe of some use.
Using that plus the InstanceContextMode property of the ServiceBehaviour attribute and the ability to configure Service throttling you should be able to get what you want.
As with #Matt, I've done it too with help from this link.
http://www.codeproject.com/KB/WCF/generic_wcf_host.aspx