WCF and FluentNHibernate - c#

I've hit a wall on this one. I have a WCF library with a respective WCF web service. A sandbox web application attempts to fire one method from this service.
The service, however, will log requests as they are made. The persistence layer here is built with FluentNHibernate. Session management in a web application has been pretty straight forward in the past(ie HttpModules), but in WCF it got a bit tricky for me.
I followed the notes and examples with the IglooCommons library and added the following line to my global.asax(residing in the web service directory).
protected void Application_Start(object sender, EventArgs e)
{
NHibernateFactory.Initialize(new SessionFactory().BuildSessionFactory());
}
BuildSessionFactory returns the following:
public class SessionFactory
{
public SessionFactory() { }
public ISessionFactory BuildSessionFactory()
{
return Fluently.Configure()
.Database(MsSqlConfiguration
.MsSql2005
.ConnectionString(x =>
x.FromConnectionStringWithKey("myConnection"))
.ShowSql()
.CurrentSessionContext<WebSessionContext>())
.Mappings(m =>
m.FluentMappings
.AddFromAssemblyOf<OneClass>()
.AddFromAssemblyOf<AnotherClass>()
.Conventions.Add(
PrimaryKey.Name.Is(x => x.EntityType.Name + "ID"),
ForeignKey.EndsWith("ID"),
Table.Is(x => Inflector.Net.Inflector.Pluralize(x.EntityType.Name))))
.BuildSessionFactory();
}
}
The service page(*.svc) loads up with its soothing stock blue "to generate classes use this wsdl" page, with no issue.
When the web application that references this attempts to call a service method,
NHibernateContext.Current().Session
is unable to find any live session. After stepping through the application, the app start method in global.asax is being fired, however seems to be dying(this is a guess) prior to any action requiring it.
I realize IglooCommons may be a bit specific as NHibernateContext is a proprietary library, however, WCF with a persistence layer isn't uncommon. Any thoughts on what I've missed or another direction to take are greatly appreciated.
Additional Note:
For the web application using this service, I've created an "interop" library which was based on the wsdl, auto-generated using svcutil. There isn't a web reference between the web app and the web service, just the web app using the auto-gen classes.

Have you enabled the ASP.NET service hosting environment for your WCF service? This requires that you:
Apply the AspNetCompatibilityRequirementsAttribute to your service with an AspNetCompatibilityRequirementsMode of Required.
That you configure the hosting environment in WCF web.config like so:
<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
<!-- rest of config here -->
</system.serviceModel>
More information about WCF Service hosting with ASP.NET is available here in the MSDN documentation.

This resolution in particular was a misunderstanding of the IglooCommons lib. The "NHibernateContext" attribute in the example was used to decorate the interface, when in reality it needed to decorate the implementation. By moving this alone, the sample on the Igloo site was able to function normally.
As a side note, the other solutions provided here were excellent in expanding the little knowledge I have of inner workings with WCF and its interaction with NHibernate.

Your WCF service svc.cs file should look like this:
[NHibernateContext(Rollback.Automatically)]
public class YourWcfService : IYourWcfService

Related

How can a WCF Service obtain Query Parameters?

I'm working on an Azure service for a Windows Phone app. I need the Azure Service to access the users' OneDrive. Following this article, my scenario should be:
The user sign in to Windows Live on the WP app.
The Live web service sends the authorization code to a redirect URI that I defined, with the code appended as a query parameter named code, as:
http://www.example.com/callback.php?code=2bd12503-7e88-bfe7-c5c7-82274a740ff
I get the authorization code and access the users' data
After investigating a lot in Service, I still can't find a way to capture the query parameter in my web service. As I am new to this area, I don't know where to focus on. I'll be really appreciated if you can give my an advise or answer my following questions:
Can I access the service just using the url with parameter in a browser? How can I see if the service is working properly?
An article mentioned using WCF [Web Get] attribute to get Query Parameters, but I still don't know how to implement both the IService1.cs and Service1.cs file, could you give me a sample about how to access the value of Query Parameter?
Thanks!
I'm not sure if i understand your problem properly but if you want your RESTfull WCF service to be the callback receiver for the request code, your Service must be hosted with a WebHttpBinding and a ServiceContract similar to this one.
[ServiceContract]
public interface IService
{
[WebGet(UriTemplate = "callback?code={requestCode}")]
void OAuthCallback(string requestCode);
}
So if the base address of your Service is "http://service.mydomain.com/MyService.svc" the OAuthCallback Method will be called when a http GET request to "http://service.mydomain.com/MyService.svc/callback?code=RequestCode" is made.

Any way to get OWIN to host a SOAP service?

How do I get OWIN to host a SOAP endpoint (do not care if WCF is or isn't involved, SOAP gives WSDL which makes services easier to consume by certain clients, that's why I want SOAP and REST)
I suspect the answer is: Implement your own middleware that hosts a SOAP endpoint. If that's the answer so be it, but that's a lot of work so I'll probably just end up sticking with WCF and avoiding OWIN if that's the case. I find it hard to believe no one has implemented a SOAP hosting middleware yet...
As a rule we like to do both REST and SOAP endpoints on our services; currently we use IIS and the WCF restful bits to host the SOAP with [ServiceContract]/[OperationContract] attributes, and the rest is defined with [WebInvoke] attributes, with these attributes the services need no reimplementation for the different endpoint types.
We just use the ASP.NET routes to add new ServiceRoutes which add a rest binding to URI/REST with the same service as a soap binding to URI/SOAP.
Now we're looking at doing some new services work and I'd like to move forward to using OWIN so we can implement our new services with hosting agnosticism as some services will be better served by windows service hosting and some better served by IIS service hosting.
All of my fiddling with things and so far I can come up with no way of getting a SOAP endpoint hosted by OWIN. I have the rest handled fine by making my service inherit from ApiController and then using this little snippet of code in the OWIN app's Configuration method:
public void Configuration(IAppBuilder app)
{
HttpConfiguration config = new HttpConfiguration();
config.MapHttpAttributeRoutes();
app.UseWebApi(config);
[...]
There is a custom OWIN middleware example on MSDN that shows how to support SOAP requests. It is not a general purpose WCF host but may be enough to expose your existing WCF Services (i.e. [ServiceContract/OperationContract]) within an ASP.NET Core app. The example does not include support for [WebGet/WebInvoke] but may be enough to get you started.
https://blogs.msdn.microsoft.com/dotnet/2016/09/19/custom-asp-net-core-middleware-example/
If your primary goal is simply to begin writing new services using OWIN and you still plan to host them in IIS using Microsoft.Owin.Host.SystemWeb. You could ignore the WCF requests within the OWIN pipeline and allow the IIS ASP.NET pipeline to handle them. This would enable you to write services that are a combination of OWIN middleware and traditional WCF endpoints.
public static class WCFAppBuilderExtensions
{
public static IAppBuilder IgnoreWCFRequests(this IAppBuilder builder)
{
return builder.MapWhen(context => IsWCFRequest(context), appBuilder =>
{
// Do nothing and allow the IIS ASP.NET pipeline to process the request
});
}
private static bool IsWCFRequest(IOwinContext context)
{
// Determine whether the request is to a WCF endpoint
return context.Request.Path.Value.EndsWith(".svc", StringComparison.OrdinalIgnoreCase);
}
}
Then call the IgnoreWCFRequests extension method when configuring your app.
public class Startup
{
public void Configuration(IAppBuilder app)
{
var config = new HttpConfiguration();
WebApiConfig.Register(config);
app
.IgnoreWCFRequests()
.UseWebApi(config)
.Run(context =>
{
return context.Response.WriteAsync("Default Response");
});
}
}
It's not so easy to host a WCF infrastructure over an OWIN one, sure it can be possible, with a bit of work it's clear possible to adapt, or proxy the owing request-response layer to the WCF infrastructure; WCF provides a not so easy but a complete infrastructure to do something like that.
cpowers answer may work for some, but didn't for me because I have other Filesystems setup within Owin, and I couldn't get both behaviors (fallback to other handlers when needed and also go through OWIN pipelines).
This was the configuration which made it work for me:
Use Owin automatic startup (Remove any appSettings named owin:AutomaticAppStartup)
Do not manually add its handlers in your web.config (or Startup will run twice) (Remove OwinHttpHandlerfrom from <handlers> in you web.config)
Add appBuilder.UseStageMarker(PipelineStage.MapHandler) after builder.UseFileServer()
UseFileServer must happen after all pipelines you setup, otherwise the ones setup after it will not work and you'll get 404
Optionally Fork the pipeline like cpower mentioned
If your OWIN pipelines does not register middlewares for the paths where your legacy stuff is you don't even need to fork your pipeline (my case).

ASP.NET Web Applications's dependency on ASMX web service

I have two projects in a solution. An ASP.NET Web Application and ASMX Web Service Application. ASMX Web Service is referenced in ASP.NET Web Application(As Web References).
In aspx page we create an object of Web Service and call methods on it like following.
MyWebService myWebService = new MyWebService();
UserDetail userDetail = myWebService.GetUserDetail(25);
This means my aspx page depends upon on concrete implementation of MyWebService. According to Dependency Inversion Principle (DIP), code should depend on abstractions, not concrete implementations and that those abstractions should not depend on details; the details should depend on the abstractions.
How do i remove this dependency?
On Google i came across following articles which is similar but not exactly to what i am looking for.
http://www.springframework.net/doc-latest/reference/html/webservices.html
http://www.codeproject.com/Articles/310677/ASP-NET-Web-Services-Dependency-Injection-using-Un
http://www.gitshah.com/2011/11/integrating-springnet-with-asmx.html
All these articles explains about injecting dependency into asmx web service and not injecting asmx web service dependency into asp.net web application.
I am newbie to term Dependency Injection and i may be thinking the wrong way and going in a wrong direction.
Plesae help me understand this confusion.
Why write this code on webpage?, you can write a layer to handle such calls and let that layer decide how to perform the operation.
This would allow you to:-
1)Loosely couple functionality.
2)Remove redundancy.
You can use a factory that's injected.
For example:
interface IWebServiceFactory
{
MyWebService client();
}
public class WebServiceFactory
{
public MyWebService client()
{
return new MyWebService();
}
}
In your asp.net web application.
var service = Locator.Resolve<IWebServiceFactory>();
UserDetail userDetail = service .GetUserDetail(25);
Note you need dependency injector in global ascx. you can ninject or ms unity or whatever injector.

How can I host multiple IoC-driven WCF services in MVC?

I have around 6 WCF services that I want to host in an MVC application, routing requests to /services/foo to WcfFooService and /services/bar to WcfBarService
I can accomplish IoC with StructureMap within the services and inject my constructor dependencies by using the example that Jimmy Bogard blogged about here:
Jimmy's article is great, but I'm trying to extend it to work with multiple services hosted within the same MVC application. Essentially, the part at the bottom is the part that is causing me a few headaches:
public class StructureMapServiceHostFactory : ServiceHostFactory
{
public StructureMapServiceHostFactory()
{
ObjectFactory.Initialize(x => x.AddRegistry<FooRegistry>());
//var iTriedThisToo = ObjectFactory.Container;
//container.Configure(x => x.[etc]);
}
protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
{
return new StructureMapServiceHost(serviceType, baseAddresses);
}
}
With a single WCF service - routing MVC requests to a specific url via the StructureMapServiceHostFactory shown above works brilliantly - but - If (for example) I create a StructureMapServiceHostFactory2 for the /services/bar call, to allow for a different Registry to be used, when the MVC app spins up, it appears to call each factory in turn as it runs through RouteConfig.cs and adds the routes, so ultimately I don't get configured instances that the first ServiceHostFactory should provide.
It doesn't make a difference if I call Initialize(); or attempt to grab the Container property and call Configure on it, either.
Am I on a hiding to nothing with this? The major reason for requiring registry isolation is due to different NHibernate configuration, but I could configure Named instances of SessionFactory and Session for NHibernate purposes and then use a single registry to get around this. In my mind I wanted the WCF service and MVC-hosting to be capable of using their own IoC containers in isolation, which is why I went down this route.
Is there any way that I can accomplish this?
Ok, so it would appear the only person capable of answering this was me, by virtue of a re-think and 're-architecting' the solution so that the problem doesn't exist in the first place.
I now have a capable way of hosting these services and maintaining IoC with StructureMap neatly per service, without any conflicting concerns.
If you find yourself in a similar position with SOA taking over (SOATO?) - taking a step back is a good start ;)

Forcing WcfSvcHost.exe to use my custom service host

Is it possible to force WcfSvcHost (which is executed automatically when I do an F5 or when I am debugging another project in the solution) to use a custom ustom service?
I have my custom service host working great in my asp.net Host container by using a service factory which in turn calls the Custom Service Base.
But when WcfSvcHost executes it's not using my custom ustom service.
Is this possible?
If not, what are my alternatives? I presume I must uncheck "Start WCF service host when debugging a project in another solution" which is in the WCF Options in app properties but then I must create a console Host container?
And I can't get the console host container to automatically execute each time I am debugging something else?
I notice this under DEBUG in app properties (maybe I can use something like this to force the loading of the custom servicehost)
/client:"WcfTestClient.exe"
The problem being is that I have my custom ServiceHost inject some UNITY (IOC) stuff, here the overriden method ... so it must execute otherwise it fails.
protected override void InitializeRuntime()
{
Bootstrapper.ConfigureUnityContainer();
base.InitializeRuntime();
}
I was trying exactly the same thing for exactly the same purpose (;-)
I thought I found a solution by not using physical .svc files anymore (which contain the custom host factory when hosting in IIS), but moving this info to the .config file instead:
<serviceHostingEnvironment aspNetCompatibilityEnabled="false">
<serviceActivations>
<add relativeAddress="~/Services/NaisTime/NaisTimeService.svc" service="Nais.Time.Services.NaisTime.NaisTimeService"
factory="Nais.Time.Services.NaisServiceHost.NaisServiceHostFactory, Nais.Time.Services" />
<add relativeAddress="~/Services/Northwind/NorthwindService.svc" service="Nais.Time.Services.Northwind.NorthwindService"
factory="Nais.Time.Services.NaisServiceHost.NaisServiceHostFactory, Nais.Time.Services" />
</serviceActivations>
</serviceHostingEnvironment>
It works for IIS, but putting the same entries in the app.config file of my Service Library project does not make SvcWcfHost use this.
I guess I am not getting my relativeAddress right.
Anybody any experience with this?
kr,
Michel Liesmons.
I don't think you can do that - you'll need to host in IIS or create your own, customized service host.

Categories

Resources