I need to host a webservice on IIS. I did this before where I will have an .svc(WCF) file or amsx file. But never did it with just a dll. How should I set it up?
Create a class like so using asp.net compatability mode...
[ServiceContract]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]
public class MyService
{
//Some methods
}
Register the class in your global.asax file as a web service
public class Global : System.Web.HttpApplication
{
public void Application_Start(object sender, EventArgs e)
{
RegisterRoutes();
}
private static void RegisterRoutes()
{
RouteTable.Routes.Add(new ServiceRoute("myServiceUrl", new WebServiceHostFactory(), typeof(MyService)));
}
}
if your app was running on port 8080 you could then hit the service at
http://localhost:8080/myServiceUrl
Related
I have a working WCF application hosted in IIS (.svc), using Ninject (Ninject.Web.Common) for dependency injection. All is well and good, works great. However I am trying to implment interception on the service endpoints and am getting a ServiceActiviationException. I've included the ninject extensions for wcf, interception, and interception.dynamic proxy as well as castle.core, so I'm not really sure what I'm missing here. Any ideas?
UPDATE: I was able to get past the service validation exception but I am now getting the following error:
Can not instantiate proxy of class: MyNameSpace.CustomerService.
Could not find a parameterless constructor.
My NinjectWebCommon contents:
public 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 PostStart()
{
// Inject the WITS Application Security service into the ApplicationSecurityRoleProvider
//_kernel.Inject(Roles.Provider);
}
public static void Stop()
{
Bootstrapper.ShutDown();
}
private static IKernel CreateKernel()
{
var kernel = new StandardKernel(
new AutoMapperModule(),
new CustomerServiceModule(),
new AccountServiceModule());
try
{
kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();
RegisterServices(kernel);
return kernel;
}
catch
{
kernel.Dispose();
throw;
}
}
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<LoggingInterceptor>().ToSelf().InRequestScope();
kernel.Bind<CustomerService>().ToSelf().Intercept().With<LoggingInterceptor>();
}
And a simple interceptor (Ive tried this also just implementing IInterceptor to no avail):
public class LoggingInterceptor : SimpleInterceptor
{
/// <summary>
/// Intercepts the specified invocation.
/// </summary>
/// <param name="invocation">The invocation to intercept.</param>
protected override void BeforeInvoke(IInvocation invocation)
{
Debug.WriteLine("Running " + invocation.ReturnValue);
base.BeforeInvoke(invocation);
}
public new void Intercept(IInvocation invocation)
{
try
{
base.Intercept(invocation);
}
catch (Exception e)
{
Debug.WriteLine("Exception: " + e.Message);
}
}
protected override void AfterInvoke(IInvocation invocation)
{
Debug.WriteLine("After Method");
base.AfterInvoke(invocation);
}
}
I have a WCF Service written in Visual Studio 2015 (c#) that uses web sockets, this means the endpoint is configured with netHTTPBindings. I have a Delphi application that I have currently written in XE and would like to consume the WCF Service, what is the best way for a Delphi application to consume a web socket WCF Service?
// Edit ---------------------------------------------------------------------------
I am now using wsDualHttpBindings, here is some prototype code:
WCF Service interface
[ServiceContract(CallbackContract = typeof(IStatusCallback))]
public interface IStatusService
{
[OperationContract(IsOneWay = true)]
Task StartSendingStatus();
}
[ServiceContract]
public interface IStatusCallback
{
[OperationContract(IsOneWay = true)]
Task SendStatus(string aValue);
}
Implementation
public class StatusService : IStatusService
{
public async Task StartSendingStatus()
{
var callback = OperationContext.Current.GetCallbackChannel<IStatusCallback>();
while (((IChannel)callback).State == CommunicationState.Opened)
{
await callback.SendStatus(GetStatus());
await Task.Delay(1000);
}
}
private string GetStatus()
{
// For now return datetime
string dt = DateTime.UtcNow.ToString();
return Convert.ToString(dt);
}
}
Here is how I consume it in a C# application, I put the result into list box.
public partial class ClientForm : Form
{
private StatusServiceReference.StatusServiceClient StatusService;
private class CallbackHandler : StatusServiceReference.IStatusServiceCallback
{
private ListBox _listbox;
public CallbackHandler(ListBox aListBox)
{
_listbox = aListBox;
}
public void SendStatus(string aValue)
{
_listbox.Items.Add(aValue);
_listbox.SelectedIndex = _listbox.Items.Count - 1;
}
}
public ClientForm()
{
InitializeComponent();
var context = new InstanceContext(new CallbackHandler(StatusListBox));
StatusService = new StatusServiceReference.StatusServiceClient(context);
}
private void StatusBtn_Click(object sender, EventArgs e)
{
StatusService.StartSendingStatus();
}
}
This works fine, I would like to know the best way to do the above client code in Delphi. When I import the WSDL file it does not have the IStatusServiceCallback interface.
My Scenerio is that i need a SignalR self Hosted WCF Service that response and sends message to all connected users that came from Winform or WPF.
I have tried alot as follows:
I have Created WCF service with SignalR Self Hosting code as below which contains 3 Classes and 1 Interface.
namespace SignalRServiceClass
{
[ServiceContract]
public interface ISignalRServiceClass
{
[OperationContract]
string GetsMessage(string name);
[OperationContract]
void Configuration(IAppBuilder app);
[OperationContract]
void Send(string name, string message);
}
}
namespace SignalRServiceClass
{
public class SignalRServiceClass : ISignalRServiceClass
{
public string GetsMessage(string name)
{
return "Message From Service " + name + "!";
}
}
}
namespace SignalRServiceClass
{
class ClassHub : Hub
{
public void Send(string name, string message)
{
Clients.All.addMessage(name, message);
}
}
}
namespace SignalRServiceClass
{
class Startup
{
public void Configuration(IAppBuilder app)
{
// app.UseCors(CorsOptions.AllowAll);
// app.MapSignalR();
app.Map("/signalr", map =>
{
map.UseCors(CorsOptions.AllowAll);
var hubConfiguration= new HubConfiguration
{
EnableDetailedErrors=true,
EnableJSONP= true
};
map.RunSignalR(hubConfiguration);
});
}
}
}
And Secondly Winform Client. I am confused here that how to manage the client code here but i put some code for testing as below.
private void button1_Click(object sender, EventArgs e)
{
//MessageBox.Show(test.GetsMessage("This is the Test Message"));
var hubConnection = new HubConnection("http://localhost:50172/");
var serverHub = hubConnection.CreateHubProxy("MessageRecievingHub");
serverHub.On("broadCastToClients", message => MessageBox.Show(message));
hubConnection.Start().Wait();
}
Please guide me in this manner.
Your Help will be appreciated. I have tried and googled alot but in vain.
Thanks alot in Advance.
You do not want SignalR, you need XSockets WCF sample
SignalR and WCF don't interoperate in this way, and don't really need to. If you're using SignalR, there's no reason to use WCF- you can publish your hub on IIS or self-hosted (see the Getting Started tutorial and the Self-Host tutorial at asp.net/signalr), and connect to it with desktop or JavaScript/HTML clients.
You can easily create a .NET client application to communicate with your SignalR server - below is a simple WinForm .NET C# client that sends and receives a SignalR message:
namespace SignalrTestClient
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
async void Form1_Load(object sender, EventArgs e)
{
var hubConnection = new HubConnection("http://localhost:8080/");
IHubProxy hubProxy = hubConnection.CreateHubProxy("MyHub");
await hubConnection.Start();
hubProxy.On("addMessage", message => onData(message));
await hubProxy.Invoke("Send", "Hello SignalR Server!");
}
private void onData(string msg)
{
Console.WriteLine(msg);
}
}
}
In your SignalR server you just need the following hub class:
public class MyHub : Hub
{
public void Send(string message)
{
Console.WriteLine("Received a message from a client");
if (message.Contains("Hello")) {
Clients.All.addMessage("Well hello there client!");
}
}
}
It is also possible to create a C++ client for SignalR
I've been trying to find a way to override the default WVF REST 4.0 helppage with my own one, and came across this post:
http://code.msdn.microsoft.com/WCF-Custom-Help-Page-6f5a90f0
I've been trying to use the same approach in an IIS hosted service using the following code:
namespace WcfHelpRestService
{
public class Global : HttpApplication
{
void Application_Start(object sender, EventArgs e)
{
RegisterRoutes();
}
private void RegisterRoutes()
{
// Edit the base address of Service1 by replacing the "Service1" string below
var factory = new MyServiceHostFactory();
RouteTable.Routes.Add(new ServiceRoute("Service1", factory, typeof(Service1)));
}
}
}
namespace WcfHelpRestService
{
public class MyServiceHostFactory : WebServiceHostFactory
{
public MyServiceHostFactory ()
{
}
protected override System.ServiceModel.ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
{
return new MyServiceHost(serviceType, baseAddresses);
}
}
}
namespace WcfHelpRestService
{
public class MyServiceHost : WebServiceHost
{
public MyServiceHost(Type serviceType, Uri[] baseAddresses): base(serviceType, baseAddresses)
{
}
public override void AddServiceEndpoint(System.ServiceModel.Description.ServiceEndpoint endpoint)
{
endpoint.Behaviors.Add(new HelpPageEndpointBehavior("ACME LLC"));
base.AddServiceEndpoint(endpoint);
}
}
}
however I keep getting the error:
[AddressAlreadyInUseException: HTTP
could not register URL
http://+:51443/Service1/help/ because
TCP port 51443 is being used by
another application.]
System.ServiceModel.Channels.SharedHttpTransportManager.OnOpen()
+1106
not quite sure what I'm doing wrong, so any help would be greatly appreciated.
TIA
Søren
Looks like this address is exclusively locked by some other application.
This could be in case :
when you are using same address for some other application.
when you have started same app twice with same address
when IIS 5.1 is used that is locking exclusively port in your case 51443.
From above, look like third one.
I want to send a data from WCF host (not service proxy) to the connected client with the service.
How can I achieve this?
You'll need to create a Duplex service. See this article for more information: http://msdn.microsoft.com/en-us/library/ms731064.aspx
Here's an example:
[ServiceContract(
SessionMode=SessionMode.Required,
CallbackContract=typeof(INotificationServiceCallback))]
public interface INotificationService
{
[OperationContract(IsOneWay = true)]
void Connect();
}
public interface INotificationServiceCallback
{
[OperationContract(IsOneWay = true)]
void SendNotification(string notification);
}
public class NotificationService : INotificationService
{
public static List<INotificationServiceCallback> Clients =
new List<INotificationServiceCallback>();
public void Connect()
{
Clients.Add(
OperationContext.Current.GetCallbackChannel<ICalculatorDuplexCallback>());
}
}
public class Notifier
{
void HandleReceivedNotification(string notification)
{
foreach (var client in NotificationService.Clients)
{
client.SendNotification(notification);
}
}
}