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
Related
I'm new to asp.net mvc and web api. I'm reading a book which says:
ASP.NET MVC uses: System.Web.HttpRequest
and Web API Equivalent is System.Net.Http.HttpRequestMessage
and below is a picture that describes the request and result flow of web api
So my question is, how does hosting environment(which will typically be IIS) know that it should create a HttpRequestMessage object to represent the request from the client? I mean if the application is a MVC application, IIS should create a HttpRequest object instead of HttpRequestMessage, so how does IIS know which one to create?
As you can see from the picture you posted, the HttpRequestMessage exists only inside the "hosting" environment, web browser client does not know anything about that.
In the "hosting" world, IIS app pool is running the code you have built and deployed which knows very well wich framewok you are using as your code also contains the using assemblies you listed, System.Web... or System.Net...
Consider that even if you have shown separation between hosting, Controller and Action, all of that is running in same App Pool in IIS which, again, runs your code so knows what it is about as your IL assemblies were built from your specific source code.
I am not sure if I understand your question but this might be what you're looking for:
I mean if the application is a MVC application, IIS should create a
HttpRequest object instead of HttpRequestMessage, so how does IIS know
which one to create?
You must remember how you differentiate between a normal MVC Controller and a Web API Controller...
WebAPI Controllers enforces this annotation [ApiController] and must inherits from ControllerBase:
[ApiController]
public class PeopleController : ControllerBase {
//Your API methods here
}
A normal MVC Controller only inherits from Controller base class:
public class PeopleController : Controller {
//Your Action methods here...
}
Those already create configuration for your APP which becomes easier for you Hosting environment to know what is going and what to return when.
I hope you find this helpful.
I've read the ABP documentation.
Here is my solution architecture for my new project based on the ABP Framework.
First of all, I want to ask if there is anything wrong with this design?
I've registered all my app services to IocManager in my Holitera.ApplicationModule.
So now I can call my app services from MVC controllers. RegionAppService is my new AppService here.
Here is the registration:
And my RegionAppService class:
public class RegionAppService : AsyncCrudAppService<Region, RegionDto,int>, IRegionAppService
{
private readonly IRepository<Region> _regionRepository;
public RegionAppService(IRepository<Region> regionRepository) :
base(regionRepository)
{
CreatePermissionName = "CreateRegionPermission";
_regionRepository = regionRepository;
}
}
Now I want to create a CRUD Razor page like the Roles view in the default template. But I couldn't register my custom RegionAppService to the JavaScript proxy services.
Do I need a dynamic Web API module to do that? Is that necessary? If it is, then how are Role, User, Customer, Account services registered to the dynamic JS proxy? I couldn't find the configuration for that. As much as I know there is no configuration for dynamic Web API module in the default MVC template? So I don't have an API module yet.
I'm going to need a dynamic JavaScript module later, but not now. First, I just want to handle this.
And by the way, what is the difference between dynamic AJAX call methods and dynamic Web API module? Are they same or if not, how?
Thanks :)
anything wrong with this design?
Entity and DomainService go in Core project. Dto and AppService go in Application project.
You can read about NLayer Architecture.
It's how the other services are discovered, and the right approach.
Do i need dynamic web api module to do that? Is that neccessary?
No.
how are Role, User, Customer, Account services are registered to dynamic js proxy? I couldn't find the configuration for that. As much as i know there is no configuration for dynamic api module in default mvc template?
It's done in YourProjectNameWebCoreModule. You can create controllers for additional assemblies:
Configuration.Modules.AbpAspNetCore()
.CreateControllersForAppServices(
typeof(RegionAppService).GetAssembly()
);
Update: As per it's request, the following is a more clean explanation of what I am trying to achieve, and a description of the context in which I am working.
Essentially, I am making a website using ASP.NET Core 2.1 with the Razor Pages framework, configured entirely with the default setup for everything. The important note is that I need to use a specific external provider as the app's data management service and thus cannot just implement a database with ASP.NET. Because of this, in the server-side code for most of the Pages, I am using a client SDK for said management service because it is easier to interact with than a REST API. The issue is that I am running into concurrency problems due to the fact that the SDK was designed to be used with one session at a time, and thus exposes static properties containing the session data such as the "current user". What I am asking is how I could possibly create a new execution or memory domain for each session that is created, so that each one can have it's own "current user", or how I could otherwise solve the concurrency nightmare that emerges when an SDK is used that is designed to only have the client deal with one user and/or session at a time in the entire backend. My previous notes about Blazor where attempting to describe the easiest analog for what I think could be a solution to this issue. I have heard about storing session data; however, as far as I am aware, everything must be serialized to JSON and stored in a file somewhere, which does not work for me as the data could be confidential.
Old Explanation (Still Somewhat Relevant): I am creating a website powered by ASP.NET Core 2.1 and am attempting to use an SDK that was designed to be used on an AppDomain that is unique to one specific application instance and/or session; this means that the SDK has multiple APIs which expose data-storage members (fields, properties, etc.) that are static. In terms of using such an SDK with ASP.NET Core, this exposure structure seems to be an issue because the runtime only allocates one single AppDomain, on the server-side, for all of the sessions collectively, and thus possibly multiple separate users, to share. If I do not have access to the source of this SDK and/or it cannot be changed, for purposes related to platform-agnosticism, how do I use the SDK successfully without only being able to store the data for one session at a time. Here is a simplified version of what I am working with:
Sample API:
public sealed class User
{
public static User ActiveUser { get; private set; }
public static int TotalLogCyclesThisSession { get; private set; } = 0
public string Username { get; internal set; }
private string Password { get; internal set; }
public string Name { get; internal set; }
public string AccessKey { get; }
public User(string username, string password)
{
/* Populate Instance Properties with Relevant Data */
ActiveUser = this;
}
public void Logout()
{
/* Clear Data from Settable Instance Properties */
ActiveUser = null;
TotalLogCyclesThisSession++;
}
}
Assume that the static variables are used elsewhere in the SDK as well.
So basically, if the API above were real, how would I use it in ASP.NET Core, so that every session would have it's own entire copy of the SDK to use, including session-specific static variables. If possible, I am looking for something like how it is possible to create a Blazor "Client" assembly, that has a new AppDomain for every session, and a "Server" assembly, though I understand that solution implemented by Blazor may not be applicable considering that it has a browser-local runtime active as well, whereas ASP.NET Core does not. Worst-case scenario, the API can be modified, but it still must be platform-agnostic to most extents. Thanks in advance for all help.
I have hard time to understand your problem. But I think the issue is some confusion about Blazor, but correct me if I'm wrong.
"create a Blazor "Client" assembly, that has a new AppDomain for every session"
Blazor is a client side SPA build on .NET and runs WebAssembly in the browser. So technically you don't have classic "sessions", no session cookie, nothing. And definitely not multiple ones because the whole context is in the browser memory which used by a single user. Think about Blazor like a JS SPA e.g. Angular or React App.
SPAs usually used with (stateless) APIs which can be authorized or not. You can do the same here. Just acquire a JWT token (OAuth2) and pass it to your API. Here is an example code which does something similar with a user object than you were asking: UserModel.cs and here is the Authorized client ApiClient.cs code.
If you want to think in "sessions" and the classic way. Technically the session is in the browser memory, SPA state. The lifetime of the session is the expiration time of the token. But it is the same with every SPA application no mater if it JS or Blazor.
I hope this helps and answers your question.
UPDATE: Since now Blazor is officially available with .NET Core 3.1 you should read about Microsoft Balzor Authentication.
I'm looking to integration test a web service built on ASP.NET Web API 2. Many things such as cookies, getting the current principal, etc. are done through HttpContext.Current.
I found the following resource on integration testing ASP.NET:
http://amy.palamounta.in/blog/2013/08/04/integration-testing-for-asp-dot-net-web-api/
This works great. It spins up an in-memory host and combined with the automated schema generation of Entity Framework 6, setup and teardown are easy.
The problem comes in when things try and use HttpContext.Current to, as aforementioned, get cookies/etc. It seems that when hosting in-memory using HttpServer, HttpContext.Current is always null. This does make a little sense given there's no real request, but is a pain - it means the integration tests can't cover anything requiring anything from this property.
What can I do here? It looks like very little of the data I'm using is present anywhere but HttpContext.Current, so am I just going to have to spin up full external instances on IIS?
In order to test your api using self host you have to avoid calling HttpContext.Current from a web api context. You can wrap it in something you can mock, like so:
public static class CurrentHttpContext
{
public static Func<HttpContextBase> Instance = () => new HttpContextWrapper(HttpContext.Current);
}
Then when you are creating your test server you could set the CurrentHttpContext to some fake HttpContextBase. For example using FakeItEasy (http://fakeiteasy.github.io/):
var context = A.Fake<HttpContextBase>();
CurrentHttpContext.Instance = () => context;
And then use this anywhere you need to access HttpContext:
var context = CurrentHttpContext.Instance();
// do what you need to do to httpcontext now like setting principal, cookies etc
I am very new to web service stuff so please be kind.
I have written a simple POJO class, and deployed it on an axis2 server:
public class Database {
private Project project;
public void login(){
project = new Project();
project.setDescription("Hello there");
project.setName("To me");
}
public Project getProject(){
return project;
}
}
I call the service from a c# client:
localhost.Database db = new WindowsFormsApplication1.localhost.Database();
db.login();
localhost.getProjectResponse pr = new WindowsFormsApplication1.localhost.getProjectResponse();
pr = db.getProject();
When I debug the response is null.
At the java end, when I call getProject, the project object is null.
What's happening?
How do I preserve the state of project between service calls?
For most toolkits, web services are stateless by default. I think axis is no different.
If you want to maintain state between calls then you will need to enable sessions. An example on how to maintain sessions in axis can be found at:
http://kickjava.com/src/test/session/TestSimpleSession.java.htm
On the .NET side you will need to assign a CookieContainer to your request to store the session identifier. See HOW TO: Use CookieContainer to Maintain a State in Web Services for more information.
I think your code would look something like this:
localhost.Database db = new WindowsFormsApplication1.localhost.Database();
// Assign the CookieContainer to the proxy class.
db.CookieContainer = new System.Net.CookieContainer();
db.login();
localhost.getProjectResponse pr = new WindowsFormsApplication1.localhost.getProjectResponse();
pr.CookieContainer = db.CookieContainer;
pr = db.getProject();
I think that should let you do what you want -- but I wouldn't recommend it.
Designing service interfaces is a bit different than designing object oriented interfaces. Service interfaces typically eschew the use of state and instead require the consumer to provide all of the relevant information in the request.
From Service-Oriented Architecture:
Services should be independent,
self-contained requests, which do not
require information or state from one
request to another when implemented.
I would definitely recommend reading that article and perhaps revisiting your design.
I'm not sure why #shivaspk left a comment instead of writing an answer, it is quite correct: web service calls (not just axis calls) are meant to be stateless, so although the project object gets created by
db.login();
when you call
db.getProject();
It is being called on a different instance of your Database class that was created by Axis to service the second call.
There is no really good answer to your question, except for you to rethink what you are trying to do. If you need some kind of authentication (via login), then that authentication needs to be part of every web service call.