Web API 2 - Unity IOC - Shared instance per request variable - asp.net-web-api

I am using web api with unity IOC.
web api client passes client-id in request header and based on this value dependencies are resolved to create a external dll's method instance.
creation of this instance take around 6-7 seconds which is creating performance issues in web api.
What I want is to prevent instance creation for call with same client-id in header.
This is how I have implemented till now:-
//========================== ArchiveFactory ==========================
ArchiveFactory archiverFactory = (HttpRequest httpRequest) =>
{
container.RegisterType<IArchive, Archive>("Archive",
new HierarchicalLifetimeManager(),
new InjectionConstructor(
new ResolvedParameter<IStoreClient>(),
Helper.GetArchiveContext(httpRequest))
);
return container.Resolve<IArchive>("Archive");
};
container.RegisterInstance(archiverFactory);
To be specific in my requirement - I am calling amazon services to retrieve images and there is a corporate dll which invokes amazon.

You can use caching mechanism at the controller/API layer(e.g Strathweb.CacheOutput.WebApi2) and you can decorate the controller method like this below. It's can cache based on parameter so if request comes in with same parameter, it will return results from cache.
[HttpGet]
[Route("")]
[CacheOutput(ServerTimeSpan = 60, ExcludeQueryStringFromCacheKey = true)]
public IHttpActionResult GetProducts(string clientId)
{
var product = new List<Product>();
return Ok(product);
}
Also, you might want to check the class constructor that you are trying to instantiate for issues that is taking it too slow. You may want to consider using lazy loading too if that will apply.

Related

Web API - Handling the long running call when aggregating the calls

I have a web api project which works as a GateWay for other Mobile clients. When the mobile client makes a call to this Gateway it internally calls the existing services which are hosted by another project and it aggregates the results and return to the client. I have recently come across a situation when my gateway is internally making 3 calls first 2 are returning the data fast but the 3rd call is taking lot of time I want to know the best way to handle this scenario.
Ensure that the return type of API action methods is async Task<YourModelDataType>.
For example, let's say you have a HomeController controller as follows:
public class HomeController : ApiController
{
public async Task<YourModelDataType> Index()
{
return new YourModelDataType()
{
Property1 = await ApiService1.GetData(),
Property2 = await ApiService2.GetData(),
Property3 = await ApiService3.GetData(),
};
}
}
Ensure that calls to the other API projects are awaited. This improves scalability on the server side. i.e. server resources are free to serve other requests while awaiting response from other API services.

Update clients in asp.net core 2.0 using SignalR

I am going through several examples on Asp.net Core WebAPI with SignalR where most of them are demonstrating simple chat application where this is what Hub returns:
return Clients.All.InvokeAsync("Send", message);
And this is how it gets called in Startup.cs
routes.MapHub<Chat>("chat");
The above example is good if message is not be send and updated to all the clients. In my case I have several APIs to be called whenever a data is changed:
Like Bank Transaction is done, I have to update ledger and several other reports at client side. But I don't see any option to pass Json.
Not finding exactly how to do this so that WebAPI gets refreshed everytime a change is there in the database.
As far as I understood, here "chat" is the endpoint which will be called from the frontend.
In this case what will happen to the endpoint I have created so far. Have a look at the below code example:
This api is to be called every time an entry is done:
public async Task<object> GetMarket(string marketshortcode)
{
Markets market = new Markets(marketshortcode);
return market.GetMarket();
}
and this the entry:
[Authorize]
[HttpPost]
public async Task<object> sellCurUser([FromBody] SellCur model)
{
if (model != null)
{
SellCurUser suser = new SellCurUser();
suser.sellcur = model;
my addition code...
}
return ....
}
There are several more endpoints which needs to be called at certain update/creation.
Now the point is how these apis will be changed or even not changed at all.
Do anyone have any example to understand it simply.

How to store PreRequestFilter information in AuthUserSession

I am building a web service using ServiceStack which has to support multiple vendors. The web service provides largely the same functionality to all vendors with some exceptions here and there.
In order to re-use as much functionality as possible I have come up with the following URL scheme:
http://localhost/brand1/templates
http://localhost/brand2/templates
"brand1" and "brand2" are not services but "templates" is. The Templates service's request DTO's will have a property called "Brand" like so:
[Route("/{Brand}/templates", "GET")]
public class GetTemplates
{
public Brand Brand { get; set; }
}
So in the Templates service I know which brand I am dealing with. This scheme works well.
What I cannot figure out though is this. The user of the service has to be authenticated and I cannot figure out how to handle the redirection of the service after the user has been authenticated since I have to pass along the brand information. I have created my own CustomAuthProvider class that inherits CredentialsAuthProvider. In the TryAuthenticate method I can set the authService.GetSession().ReferrerUrl property to the correct brand if I know what it was.
The only way I have found so far to get this information is to register a PreRequestFilter. My thinking here was that since the URL (e.g. http://localhost/brand1/templates) contains the brand I can store it in my own AuthUserSession class. I can't figure out how to do this. I have a "SessionFactory" method that I pass to the AuthFeature constructor. But what should I do in there? How do I get to the brand that I've obtained in the PreRequestFilter? Is it safe to store it in a field of the AppHost? I think not because of concurrency issues. How do I tie the PreRequestFilter to the SessionFactory method?
I hope I am explaining my problem clearly enough?
I was overthinking the solution because I didn't realize that I had all the information I needed in the IServiceBase parameter of the TryAuthenticate method of the CredentialsAuthProvider class.
In the end I came to the following solution:
public class CustomCredentialsAuthProvider : CredentialsAuthProvider
{
public override bool TryAuthenticate(IServiceBase authService,
string userName, string password)
{
var session = authService.GetSession();
var origQuery = authService.Request.UrlReferrer.Query;
session.ReferrerUrl = "/error";
var queryString = origQuery.Substring(10); // strip "redirect="
var decodedUrl = HttpUtility.UrlDecode(queryString);
if (!string.IsNullOrWhiteSpace(decodedUrl))
{
var query = new Uri(decodedUrl);
session.ReferrerUrl = query.AbsolutePath;
}
return DoAuthentication(userName, password);
}
}
The different places where you can set the Url to redirect to during ServiceStack Authentication, in order of precedence are:
The Session.ReferrerUrl Url if it's populated
The Continue QueryString, FormData param when making the request to /auth (i.e Authenticate.Continue property)
The HTTP Referer HTTP Header
The CallbackUrl of the current AuthProvider used

How to delay the response of my Web API

I am working on a Web API project and that has an Artist Web API Controller. On there, there is the api/artist method that is a GET for all artists.
When making the call to this method, I would like a 3 second delay before I serve the data, how can I achieve this?
CODE
public class ArtistController : ApiController
{
private GlContext db = new GlContext();
// GET api/Artist
public IQueryable<Artist> GetArtists()
{
return db.Artists;
}
}
I know that you wouldn't want to do this in a production environment, but I am playing with preloaders, and in order to test them properly I need to introduce this delay.
If it is just for testing you can always go for Thread.Sleep(3000)
http://msdn.microsoft.com/en-us/library/d00bd51t%28v=vs.110%29.aspx

Autofac - handle multiple requests in ASP.Net MVC 3

I am new to Autofac and IoC so now I try to build my firs ASP.NET MVC 3 application with IoC.
Here with this code I try manually to register ProductController (in Global.asax).
protected void AutofacIocRegistration()
{
var builder = new ContainerBuilder();
//PRODUCT CONTROLLER
var registration = builder.Register(c => new ProductsController(c.Resolve<IProductRepository>()));
builder.RegisterType<ProductsController>().InstancePerHttpRequest();
SqlProductsRepository productRepository = new SqlProductsRepository(DATABASE_CONNECTION);
builder.RegisterInstance(new ProductsController(productRepository));
IContainer container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
}
When I build the application for the first time, I get list of 4 products in the HTML page (as I expected), but when I refresh the page or go "next" to other list of products then I get the error
A single instance of controller
'WebUI.Controllers.ProductsController'
cannot be used to handle multiple
requests. If a custom controller
factory is in use, make sure that it
creates a new instance of the
controller for each request.
As you can see in this code
builder.RegisterType<ProductsController>().InstancePerHttpRequest();
I try to solve this with InstancePerHttpRequest() method but unsuccessful, if you have any suggestion please post.
Thanks for any help in advance.
use the below method to register your controllers
builder.RegisterControllers(Assembly.GetExecutingAssembly());
if you are using constructor injection in the controllers you can register your repository like this
builder.RegisterType<SqlProductsRepository>().As<IProductRepository>();
this way it will create the object graph when it needs to create the controller

Resources