I need to run my application which provides some ASP.NET Web API services on both IIS and .NET CLR self host modes.
I developed my ASP.NET Web API services based on OWIN and it is working fine on both hosts.
For now I need something like this:
public class OwinContextInfrastructure
{
public static IOwinContext Current
{
get
{
if (HttpContext.Current != null)
{
return HttpContext.Current.GetOwinContext();
}
else
{
// What should I do here ?
return null;
}
}
}
}
to get current owin context whenever I need in my application.
My code is working fine on IIS, but what should I do in .NET Self Host mode ?
You can use Request.GetOwinContext() for both web-hosting and self-hosting. GetOwinContext is an extension method for HttpRequestMessage and is defined in the System.Web.Http.Owin.dll assembly.
UPDATE
I have answered your original question, which is how to get OWIN context in both web-hosting and self-hosting. Now, through your additional question in the comment, you have significantly broadened the scope of your question. There is a fundamental problem though. IOwinContext is not a OWIN thing, it is a Katana thing. You cannot expect any framework hosted on OWIN to provide a context in the form of IOwinContext. ASP.NET Web API does but not every framework is supposed to. IOwinContext is an abstraction over OWIN environment dictionary and this dictionary will be available to any OWIN middleware. However, by working on top of a framework, you no longer can access the OWIN environment directly but only through how that specific framework has decided to expose the context.
For Nancy, you have to use NancyContext to get to the Items dictionary and look for the value corresponding to the key "OWIN_REQUEST_ENVIRONMENT". For SignalR, Environment property of IRequest gives you access to OWIN environment. Once you have the OWIN environment, you can create a new OwinContext using the environment.
First, I've to correct my question.
HttpContext.Current is available in applications which are based on ASP.NET and integrated IIS pipeline.But We can't use this class without asp.net anywhere, even on IIS integrated pipeline.
Answer:
1- Anywhere you need IOwinContext, you've to get it, using dependency injection, for example by constructor injection.
2- Configure everything to work based on Owin, SignalR is Owin based only, but use Web Api & owin together, and use nancy for server side views if any. Instead of writting IIS or ASP.NET handlers and modules, develop owin middlewares.
3- Using Autofac.Owin & AutoFac.WebApi & AutoFac.WebApi.Owin & Autofac.SignalR, you can setup dependency injection working across all owin middlewares you've in your application.
4- Autofac will instantiate web api controllers, signalr hubs and owin middlewares, and it will pass IOwinContext instance to classes you want using constructor injection.
My tests are ok on Owin IIS/Helios (without asp.net) , Owin SelfHost and even Owin Test Server.
This approach is similar to asp.net vNext. You can easily migrate your app to asp.net vNext, when it is production ready.
Related
I need some clarification on API versioning in .Net Core framework.
My client want the version to be handled in Router level. Like
[Route("1/[controller]")]
public class SampleController : Controller
{
[HttpGet("version")]
public IActionResult GetVersion()
{
return Ok({"Message": "API Version 1"});
}
}
I access this using, https://www.somedomain.com/api/1/sample/version
In IIS, I will create an application called 'api' (The path 'api' in my URL will be taken care here) under default web site and host my code here.
In order to do API versioning, what is the better way that I can follow here.
Can I do this?
[ApiVersion("1")]
[Route("{version:apiVersion}/[controller]")]
public class SampleController : Controller
{
[HttpGet("version")]
public IActionResult GetVersion()
{
return Ok({"Message": "API Version 1"});
}
[HttpGet("version"), MapToApiVersion("2" )]
public IActionResult GetVersion()
{
return Ok({"Message": "API Version 2"});
}
}
Is it possible to create an application under an application in IIS. Like,
Default Web Site - > api -> 1 -> Code without API version mentioned
Default Web Site - > api -> 2 -> Updated Code without API version mentioned
Or can I create the versions as application in IIS and deploy the code under each applciation version. Like,
Default Web Site - > 1 -> Code without API version mentioned
Default Web Site - > 2 -> Updated Code without API version mentioned
This will end up in changing my API URL, which i don't prefer. I still want to go with the same URI.
I access this using, https://www.somedomain.com/api/1/sample/version
Please advise the best approach that I can follow here.
Here is a popular repository that provides a set of libraries for adding API versioning to ASP.NET Web API, OData with ASP.NET Web API, and ASP.NET Core applications.
For ASP.NET Core applications, you can install this repository's ASP.NET Core API Versioning by running the following command in the Package Manager Console:
Install-Package Microsoft.AspNetCore.Mvc.Versioning
Perhaps the Map extension method of ApplicationBuilder suits your needs :
app.Map( "/1", myVersion1MappingFunction)
in the Configure method of Startup let myVersion1MappingFunction configure a separate middleware pipeline:
private static void myVersion1MappingFunction( IApplicationBuilder app)
{
// start your special middleware for version 1
app.UseMvc( routes =>
{
routes.MapRoute( ... );
}
}
On using Map extension the fragment ("/1") is removed from HttpRequest.Path
If I understand you correctly are wanting to use URL Path Segment Versioning for ASP.NET Core. With that said in your examples you will NOT have separate website deployed. You have one website deployed and you do NOT create multiple applications for versioning under your default website.
With URL path segment versioning you have one web application and that application manages all routes using the ApiVersion convention. You will need to maintain the code in such a way that it can deliver old functionality with new functionality and manage all dependencies.
I would recommend reading what Microsoft has to say about this here and doing a simple proof of concept that makes sense for your implementation.
I hope this helps clear up your confusion about deploying the application multiple times for versioning.
In your case the best method would be to employ the versioning from the web server level so you can have different deployments and a folder per version without specifying a version in the application routing itself. (your option 2/3?)
However since IIS merely proxies requests to kestrel with .net core unlike asp.net, you'll have to setup the reverse proxy by URL/URL Re-write with ARR to different versions of the deployment.
So you could have:
/root/V1/
/root/V2/
etc... like you explain.
Each deployment would be running kestrel with different ports numbers and IIS would re-verse proxy to them by URL.
Here is an article on how to setup ARR with url-write. it's written with asp.net in mind, but it's the same principal:
Reverse Proxy with URL Rewrite v2 and Application Request Routing
Where can I extend ASP.NET current (5.0) Identity functionality to easily resolve the integer user ID and security rights associated with a claim?
This should be available within all of my web application browser service access points (everywhere a cookie or JWT is provided), including SignalR hub, MVC controller, and WebAPI controller. It should work with OWIN Authentication.
Here are the three most-related solutions I've seen, and why they don't work:
Set HttpContext.Current.User in every call via global.asax Application_PostAuthenticateRequest. I've seen older (MVC 4) functionality that obsoletes this. I know global.asax is generally not the way to go today. I'm also using OWIN; this may not even work at all.
Override ClaimsPrincipal ClaimsAuthenticationManager.Authenticate() with the configuration <system.identityModel><identityConfiguration><claimsAuthenticationManager type = "CustomClaimsAuthenticatonManager" /> However, ClaimsAuthenticationManager is from System.Identity, which isn't even in the references of my ASP.NET 5.0 project with ClaimsAuthentication active. Instead I have references to Microsoft.AspNet.Identity.Core stuff in my project from current NuGet packages. It seems this approach is not for ASP.NET apps, or at least not current ones?
Set UserManager.ClaimsIdentityFactory to a custom ClaimsIdentityFactory, with overridden CreateAsync. This looks like this might work, but I don't see any way to graft that onto the current ASP.NET default behavior. See here: How to set a custom ClaimsPrincipal in MVC 5?
We have web application written in ASP.NET webforms with some asmx web services. Now we want to add some toher web services, which will serve different purpose than the old ones. We decided to use WCF framework.
My colleague created a new project in our solution, where he implemented the web service. Unfortunatelly he did not use the WCF* project templates, but normal console application with the following method for starting the WS:
public static void StartWS() {
if (_selfHost!=null)
StopWS();
Uri baseAdress = new Uri(WSIntegrationService.ServerUrl);
_selfHost = new ServiceHost(typeof(WSIntegrationService), baseAdress);
_selfHost.AddServiceEndpoint(typeof(IWSIntegrationService), new WSHttpBinding(SecurityMode.None), WSIntegrationService.EndPointName);
_selfHost.Description.Behaviors.Add(new ServiceMetadataBehavior { HttpGetEnabled = true });
_selfHost.Open();
logger.Info("Integration WS started on adress " + baseAdress);
}
Now I have to integrate the project to our web application (another project in solution).
What is the easiest way to do it?
How can I ensure that both - the old asmx service as well as the new WCF service is operational?
In the end the solution was not that hard:
In web app project choose Add New Item -> WCF Service. This should create Service.svc, Service.svc.cs and IService.cs. It also modifies your web config. Now you can try if it works, with the auto generated method DoWork. Simply use something like SoapUI app to do that. ALso you can try to browse to the svc file and check the wsdl (e.g.http://localhost:2753/WSIntegration/Service1.svc?wsdl)
Delete the files IService.cs and Service.csv.cs. Modify the Service.svc file, so it contains just the reference to the class implementing the WS, e.g. like this:
That's all. I haven't deploy the solution to the IIS yet, but I don't expect any problems there. As soon as I will do that. I will update the unswer if any additional steps will be needed.
I am familiar with web method. Now I got a suggestion to use web API instead of web method. I had done a demo of ASP.NET web API it's more closer to a MVC architecture am using the classical asp.net web development. I don't like to mess up the controller (MVC concept) with classical development.
My web Method :
[WebMethod]
public static string GetName(int id)
{
return "testName";
}
My Web API controller:
public class MyController : ApiController
{
[HttpGet]
public string GetName(int id)
{
return "testName";
}
}
am really confused on this issue any one have a better idea on the same.
What is your suggestion on the same which is the better option?
How can i compare, if both having same piece of code?
The classic ASP.NET WebServices (what you call WebMethod) are a deprecated technology. There is no longer any active development. The ASP.NET Web API is a complete rewrite of the web stack from Microsoft in which you have far greater control for creating RESTful web services. This doesn't mean that you should choose between one or the other. There's also ServiceStack. If you are starting a new project you should stay away from classic webservices. If they are still present in the .NET framework it is for compatibility reasons with legacy code.
Complementing Darin's answer, if you want to test your method from ApiController, you can inject the object's dependencies using an DI container (http://www.asp.net/web-api/overview/extensibility/using-the-web-api-dependency-resolver). The dependency injection is done automatically.
However, with webmethods, you can't use DI in that way because webmethods must be static. If you insist in using DI, you need to instantiate and call the container directly in each of the webmethods to get the dependencies to work on.
For example, in a ASP.NET page you would do something like
Cache.Add({...}) and access it via Cache["key"]. In this context, Cache is the System.Web.Caching.Cache object.
Is there anyway to do this type of ASP.NET application level caching in web API controllers?
Take a look at the MemoryCache class. From its MSDN documentation:
The MemoryCache class is similar to the ASP.NET Cache class. The
MemoryCache class has many properties and methods for accessing the
cache that will be familiar to you if you have used the ASP.NET Cache
class. The main differences between the Cache and MemoryCache classes
are that the MemoryCache class has been changed to make it usable by
.NET Framework applications that are not ASP.NET applications.
You can create a new instance of a MemoryCache yourself, or you can use the default AppDomain-wide instance via the MemoryCache.Default static property.
Edit: You'll need to add a reference to System.Runtime.Caching.dll if you wish to use this type.
If you are web hosting, why not?
var context = HttpContext.Current;
if (context != null)
{
if (context.Cache["g"] == null)
{
context.Cache["g"] = 9.81;
}
}
But you are adding a dependency on ASP.NET by doing so. Even though ASP.NET Web API has ASP.NET in the name, the Web API is host-agnostic. That is, ASP.NET/IIS is not the only hosting option; the Web API can be self-hosted as well. Something for you to consider before going down that route.
You need to type
HttpContext.Current.Cache
to access the instance. There is no Cache property declared at the Controller level, like on a Page.
Note that the context that hosts the API will need to support caching.
If you are referring to Output caching in ASP.NET Web API. Take a look at this project,
https://github.com/filipw/AspNetWebApi-OutputCache