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
Related
What I want: My Web App, to call my Protected Web Api, which in Turn calls another Web Api on behalf of the originally Web app user.
Issue : My [Authorize]'d Web Api Methods are actually returning the HTML of the Sign in your Account page, versus the content of my page.
I was able to reproduce this by doing the following
Download the git example here https://github.com/Azure-Samples/active-directory-dotnet-admin-restricted-scopes-v2
Add a Web API Blank Controller.
Add the following Code
[Authorize]
[HttpGet]
public async Task<string> Test()
{
return "Test ok";
}
*This works if I call it from a Web Browser directly and you get prompted to login properly but since what I want is an OnBehalfofFlow, I need a Client to call the Web Api, versus a browser.
I have a Web App client that is registered and configured to call a .NET CORE version of my Web API OnBehalfOfFlow and it works perfectly. However, I need to use some Asp.NET Framework stuff that doesn't work in core, so I am converting to .NET Framework.
So I take the GroupManager example above and configure it to use the same settings as my .NET CORE AD App Registration.
I then take my GroupManager and run it locally in the browser.
I then point my Client at that Uri, instead of my .NET CORE app
The calls are made, but instead of getting real responses, I merely get back a text represtentation of the HTML for the Microsoft Sign On Screen...
point the Client back to my .NET Core and it works perfectly. I am only changing the Uri here as the GroupManager sample and the .NET Core are the same otherwise.
Any thoughts on what is going on?
Thanks!!!!!
I have a problem with publishing Web API in Visual Studio.
In VS, when I publish the Web API, it is published as dll's, and when we have several controllers it is going to aggregate those into one dll.
But I have project that can have different controllers, like:
Android.cs
CoWorker.cs
TelegramBot.cs
and when I publish the project, I would like to publish the controllers in separated DLL's, because I should have update the controllers continuously and when I have an error in a specific controller, I can't publish another.
Please help!
What you are looking for will not happen on its own. If you want a plug and play like architecture where you can just publish only a module without re-publishing the whole solution.
To achieve this you need to move your controller(s)/module as a separate project (separate library). One of the useful configuration feature of ASP.NET Web API is that it allows you to define about the assemblies into which it will look to discover your controller types.
This is very useful if you have external assemblies and are not part of the Web API project.
You can implement interface System.Web.Http.Dispatcher.IAssembliesResolver GetAssemblies() or even can extend the DefaultAssembliesResolver as following.
public class CustomAssembliesResolver : DefaultAssembliesResolver
{
public override ICollection<Assembly> GetAssemblies()
{
//Your implementation here
}
}
You can find more details on this on following link.
MSDN
Sample
I think what you're looking for is a MICRO-SERVICE architecture ...
https://learn.microsoft.com/en-us/dotnet/standard/microservices-architecture/multi-container-microservice-net-applications/data-driven-crud-microservice
https://github.com/dotnet-architecture/eShopOnContainers
you can use .NET full framework
or the new .NET Core (it depends on what you have to do)
I have a strange problem for which I can't find a solution.
Currently we have a development Server (running a normal Azure Virtual Machine) and a production Server running a Web Role in Azure Cloud Services.
For the Web Role we need to add the "RoleEntrPoint" class.
But as soon this class is present, the Web Api on a normal VM on development server with IIS 8 returns a "404" for all routes.
This problem is similar to: http://jake.ginnivan.net/web-api-problem-404s-for-everything/
(As a side note, opposed to the blog post I'm not using EntityFramework. We just added the RoleEntryPoint class and copy local for Microsoft.WindowsAzure.ServiceRuntime is true)
But I can't find a solution or catch any errors thrown.
Do you have any ideas on this?
It makes sense that if you're not running as an Azure role, then RoleEntryPoint would break things. Can you make your development VM also a Web Role? If not, then don't use RoleEntryPoint and use ASP.NET lifecycle management methods instead.
From the documentation:
Web roles can optionally extend the RoleEntryPoint class, or can use the ASP.NET lifecycle management methods to handle the start and stop sequences.
So, the ASP.NET methods will work for both VM and Web Role. You didn't say what you're trying to do with the RoleEntryPoint, so I'm not sure what further guidance to give.
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.
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.