Ajax call to the Asp.net Web API controller - c#

As part of the project we have implemented ASP.Net Web API, which returns the Json data, which is consumed by the Javascript using Angular JS on the client.
Controller code is straight forward (Trimmed description):
public class CardController : ApiController
{
// code
[HttpGet]
public CardDataGetUI GetCardDataUI(int userID, int dashBoardID, int cardID)
{
// Access the application Cache object using HttpRuntime (System.Web.Caching)
var blCache = HttpRuntime.Cache;
// Create a user specific BL access key by concatenating the user ID
string userBLAccessKey = WebAPIConstant.BlUserDashboardCard + userID;
// Access the BL object stored in the Cache
accessBL = (Bl)blCache[userBLAccessKey];
// Other Code
// Fetch the data for the control being passed
cardDataUI = accessBL.GetCardDataUI(dashBoardID, cardID);
return (cardDataUI)
}
}
The above mentioned GetCardDataUI delivers the card data for different type of control like chart, map and grid on a same UI screen, so what UI does is make an Asynchronous call to all in one go, currently I have BL (business layer) object being accessed from application wide cache, which is an issue for Multi threaded access, as they would share same object, so I have converted that to a local copy and initialized the one for each call to the controller. However that is also good enough till the each ajax call is having it's unique controller instance to call the method. However in this case it seems the http call they make have same instance thus modifying the input variable of each call thus leading to unexpected result and exception, since it is modifying the internal DS at run time. It is akin to calling the static method
Ideally I did not expected a multi-threaded call to the business layer, but it seems in Angular JS client has to make such calls, they cannot be synchronous.
Currently I have resolved the situation by introducing a lock in the controller, which certainly allows one thread at a time
However was looking for a solution like each Ajax call can have it's own controller instance, when it make the http get call.
We also have an option of modifying the above mentioned controller method like:
public CardDataGetUI[] GetCardDataUI(int userID, int dashBoardID, int[] cardID)
{
// Code
}
In this case there will be one call for all cards and I will call the data fetch in a for loop, thus synchronizing the operation, but this is not much different from locking the controller, preferable will be a separate controller instance for each AJAX call
Any suggestion?

Related

Why is my Lazy<T> re-initializing every time I call Value?

I have a member of my controller
private Lazy<MyCache> loadedComponentCache = new Lazy<MyCache>(() =>
{
MyCache instance = MyCacheb.Instance;
instance.LoadStuffAsync().Wait();
return instance;
}, LazyThreadSafetyMode.PublicationOnly);
that I'm using to lazy-call a long-running method LoadAsync() that will only need called if a certain API endpoint is hit after the user goes to the page.
[HttpGet]
public ActionResult GetStuff()
{
var results = from component in loadedComponentCache.Value.All()
// ...
}
Any idea why it's re-loading every time the API endpoint is hit? My understanding is that an instance of my controller is created only when the user goes to the page and thus this will only be hit once per API call per user visiting the page.
You could make loadedComponentCache static but that's not ideal. If you are using an IoC container you could register it as a singleton. These long lived objects are generally to be avoided though if possible.
If you you truely need this long lived cache then you should probably consider using something like Redis which is designed and optimised for this sort of scenario and can be distributed across multiple nodes. https://redis.io/topics/introduction

C# dotnet core 2 pass data from middleware/filter to controller method

currently we are writing a web application with dotnet core 2.
We actually create some kind of multi-hosting platform where we can register new clients based on the url passed to our application.
However currently we wanted to create a middleware/filter to validate our client's.
Actually what we wanted to do is pull an object from the database and check if it exists, if yes, we want to call the controller method and make the object accessible, if it does not exist, we actually want to abort and show an error page.
What we already have done is created a filter/middleware that does exactly that, however we couldn't figure out a way to access the object that we already pulled in our filter/middleware inside the controller method.
is there actually any documentation for doing that?
I actually tried to figure it out from:
https://learn.microsoft.com/en-us/aspnet/core/fundamentals/middleware?tabs=aspnetcore2x
https://learn.microsoft.com/en-us/aspnet/core/mvc/controllers/filters
but they don't describe a way to do it, only to actually do something before/after the action.
You could add the object to the context using HttpContext.Items which the docs state:
The Items collection is a good location to store data that is needed only while processing one particular request. The collection's contents are discarded after each request. The Items collection is best used as a way for components or middleware to communicate when they operate at different points in time during a request and have no direct way to pass parameters.
For example, in your middleware:
public class MySuperAmazingMiddleware
{
private readonly RequestDelegate _next;
public MySuperAmazingMiddleware(RequestDelegate next)
{
_next = next;
}
public Task Invoke(HttpContext context)
{
var mySuperAmazingObject = GetSuperAmazingObject();
context.Items.Add("SuperAmazingObject", mySuperAmazingObject );
// Call the next delegate/middleware in the pipeline
return this._next(context);
}
}
Then later on in your action method, you can read the value:
var mySuperAmazingObject = (SuperAmazingObject)HttpContext.Items["mySuperAmazingObject"];
One way of doing it (not saying it's the only or the best) is to have DI inject a proxy of the object, you set the real value of the object in your middleware, then you can access it from the proxy in the controller.
Note: if you'll pass the proxy object in the method call instead of controller, don't forget to mark it with [FromServices] attribute.
Another way would be adding the object to the request Items property. but when you read it you'll need casting from object to your actual class.

Selfhost Web API parameter passing

I have middle ware with different components interacting with each other. I'm building now a selfhost Web API using OWIN and .NET WebAPI to interact with 3rd parties. My problem is that I need to pass an object reference to my controller so when the controller is called via a GET or POST request it can call function of the passed object. Dependency injection is not helping me in this case cause I need to pass a reference of an existing object and not create a new one.
The WebAPI is created in the ExternalWebAPI class start function:
public virtual void Start()
{
server = WebApp.Start<WebAPIStartup>(url: baseAddress);
UpdateStatus("Active","True");
}
Right now my controller looks like this:
class TradesController:ApiController
{
TradeRequest PostTradeRequest(TradeRequest tradeRequest)
{
return tradeRequest;
}
}
What I want to be able to do is to pass a reference to the TradesController of the ExternalWebAPI class using thisso from TradesController I would be bale to call ExternalWebAPI functions. I looked into DI, but I haven't found a good way to do it since it important to pass the instance of the ExternalWebAPI class that has started up the WebAPI cause it has other methods and events that has to be called once the TradesController's PostTradeRequest is called.
I think you are going down the wrong path here. Your API should take data in and send data out. It should not hold references to anything or call functions on those references. Call you API for the data you need to update your local reference and then call the function on that object as needed.

SimpleMembershipProvider intermittently returning wrong user

I am administrator of a small practice project web application, AngularJS front-end pulling its back-end data from a C#/.NET WebAPI, and I'm handling security using the SimpleMembershipProvider.
I suspect that the way I implemented said security is not the best (I'm told ASP.NET Identity is now the way to go?) but that's another question altogether.
The issue that I'm very bewilderingly running into is that I get occasional reports that on a given page load to display a particular user's data, it returns somebody else's. Reloading the page fixes the issue (evidently) and I haven't been able to duplicate the scenario myself, or figure out anything particularly consistent in the users to which this happens.
None of the information being displayed is at all sensitive in nature (the app's just a friendly front end for an already public third-party API) so I'm not in panic mode about this, but I am both concerned and confused and want it fixed.
Here is what one of my API controller endpoints looks like:
[Authorize]
public class UserController : ApiController
{
private static int _userId;
private readonly IUserProfileRepository _userProfileRepository;
public UserController()
{
_userProfileRepository = new UserProfileRepository(new DatabaseContext());
_userId = WebSecurity.GetUserId(User.Identity.Name);
}
public UserProfileDto Get()
{
return _userProfileRepository.GetUserProfileById(_userId).ToDto();
}
}
Any feedback on where I might be going wrong here or what might be causing the intermittant inconsistency would be very much appreciated. (Laughter also acceptable if the way I handled this is just really bad. :P )
Static class fields are shared by all instances/threads of the same AppDomain (in your case - process). Different http requests are processed by threads running in parallel. Any two threads running [almost] at the same time may (will) change the value of _userId. You are assigning _userId in the constructor of your controller, and a new instance of this controller is created for each http request that is to be responded to by UserController. Therefore, this assignment will happen multiple times.
You will have hard time replicating this problem, since you are a single user testing the code, hence there are no overlapping request threads.
Remove static specifier from the _userId field declaration of the controller class.
Note: make sure that DatabaseContext is disposed of. One place that can be used for this is the overriden Controller.Dispose.
Change the Get to retrieve the user id rather than from a static variable:
public UserProfileDto Get()
{
return _userProfileRepository.GetUserProfileById(WebSecurity.GetUserId(User.Identity.Name)).ToDto();
}

How to receive value from an asynchronous method located in a seperate class?

I was working on an application that makes quite a few requests using the HttpWebRequest class to bring back data from the web. Now my app makes nearly identical calls in multiple parts of my application. This is turning into a problem because I'm duplicating a lot of code.
The ideal solution would be to encapsulate the logic that makes the calls to the web in it's own class that way updating is a breeze and it can be reused throughout my application. I'm just not sure how to make an asynchronous call in a separate class and return the value to my main code behind so I can update the UI with the data.
Can someone provide me with some guidance on how to make this happen? I know this has to be possible because developers are doing it all the time when following the MVVM pattern.
I'm using Silverlight/C#.
We have code like this in our Silverlight app for use with WCF Data Services. You could probably do something similar for your web requests:
Here is some sample code (untested) (note that I have not actually ever written any code that does web requests, but maybe the async pattern is similar to other stuff that I have done in Silverlight):
public class WebRequesterHelper
{
Action _callback;
public void MakeWebRequest(object whateverYouNeedForTheWebRequest, Action callback)
{
_callback = callback;
//Make your async web request here, passing the helper object's callback.
IAsyncResult result = yourWebRequestObject.BeginGetResponse(new AsyncResultCallback(WebRequestCallback), yourRequestState);
}
public void WebRequestCallback(IAsyncResult result)
{
//Do whatever you need to do as a result of the web request, then call the callback.
if (_callback != null) callback();
}
}
In your code that wants to make a web request:
var helper = new WebRequestHelper();
//Setup the web request
object request = SetUpYourWebRequest();
helper.MakeWebRequest(request, OnWebRequestCompleted);
Your helper callback:
public void OnWebRequestCompleted()
{
//Web request is finished, what do I want to do?
}
Note that you might want your callback (which you pass to the WebRequestHelper object) to accept a parameter and you could pass information back out from the web request callback function (in the WebRequestHelper object).
Since your web download code is effectively your business logic I would definitely encapsulate it in it's own class as you planned. Then you should use events to notify your UI of state changes.
For example, your "WebRequestManager" instance can encapsulate all the thread handling and will raise events to allow the UI to respond accordingly. You would raise an event on TaskCompleted and perhaps also at intervals to provide looking feedback such as AsyncProgressChanged.
NOTE: By way of convention, I would tend to prefix any events that are likely going to be called from a thread other than the original calling one with the name "Async" so that the UI handler knows to join back onto the UI thread.

Categories