I have two ASP.NET applications running on the same server and sharing the same database. One is the front-end, developed with MVC, that caches data to avoid database calls to retrieve the same objects. The other is the back-end, developed with WebForms, that is used to manage CRUD operations.
I'd like to invalidate the front-end cache when a back-end operation occur. I don't need a refined mechanism... back-end will be used only sporadically and could invalidate ALL cached objects.
I've come across some solutions, but they're not very clean solutions... like, putting a flag on a db settings table, using a shared configuration file, calling a front-end web service from the back-end application. Every solution needs to be applied every time a front-end page is called, so I need it to be less resource consuming as possibile.
I don't want to use memcached or AppFabric or similar 'cause I think they're overkill for my basic needs.
Thank you very much!
You can just make an action that will invalidate cache. You can pass it a secret token to check if the request comes from your other web application for security.
So it will look like this:
public ActionResult Invalidate(string key)
{
if (key == ConfigurationManager.AppSettings["ApplicationSecurityKey"])
{
_cacheService.Invalidate();
return Content("ok");
}
return null;
}
In both web.config files of both projects you will have:
<appSettings>
<add key="ApplicationSecurityKey" value="SomeVerySecureValue" />
</appsettings>
And you can call it from your other web application like this:
WebClient client = new WebClient();
client.QueryString.Add("key", ConfigurationManager.AppSettings["ApplicationSecurityKey"]);
string response = client.DownloadString(url)
Related
I would like to block Users to access the content from a Back-End Api call, that gets some users(so that if they write the URL,to obstruct the users access), but to be accessible when the Front-End calls the Back-End. I host the application in IIS, I use C# as Back-End and Angular as Front-End.
You can do this by including a simple Guid token in the call.
Specify the token in the web.config app settings section.
<appSettings>
<add key="ValidToken" value="12345678-1234-1234-1234-123456789012" />
</appSettings>
Then in your API method:
public HttpResponseMessage yourcall(string token)
{
var validToken = ConfigurationManager.AppSettings["ValidToken"];
if(validToken != token) return null; //or do something else
....
}
Edit: Sorry having reread your question, the above might not be suitable, as the call is coming from client side. As Oliver mentioned the information about the call would be visible in the network tab. This is more suitable when the call is less exposed (i.e. between applications).
I am currently working on a school project with a classmate. We've decided on making the classic setup of an Administration-client (Blazor Server) and a Member-client (Angular).
We have 7 Projects in the solution so far:
Solution
├───Project.MemberClient (Angular)
├───Project.AdminClient (Blazor Server)
├───Project.Api (REST API)
├───Project.Application (CQRS & Mediatr)
├───Project.Core (Entities, Enums, Interfaces)
├───Project.Infrastructure (Database Context & Migrations)
└───Project.Test
We're using EntityFramework for the database, which both the API and Blazor Server have access to, through Mediatr.
Unfortunately, we can't come to terms with how we should handle the use of the API.
My classmate is convinced that both Blazor Server client and the Angular client should go through the REST API.
I'm convinced that we don't need to go through the API with the Blazor Server-client, since it can access Mediatr through Dependency injection. I feel it's silly to go through the API to deserialize a C# object to JSON just to serialize it again straight after.
This is a request on the API:
[HttpPost("organizr-user")]
[ProducesResponseType(StatusCodes.Status200OK)]
public async Task<ActionResult<OrganizrUserResponse>> CreateOrganizrUser([FromBody] CreateOrganizrUserCommand command)
{
var result = await _mediator.Send(command);
return Ok(result);
}
This is a request on Blazor Server:
private async Task OnButtonSave_Clicked()
{
_userCreated = false;
_showErrors = false;
var query = new RegisterUserRequest
{
FirstName = _firstName,
LastName = _lastName,
Gender = (Gender)_gender,
Address = _address,
PhoneNumber = _phoneNumber,
Email = _email,
Password = _password,
ConfigRefreshPrivilege = _refreshConfiguration
};
var result = await Mediator.Send(query);
if (!result.Succeeded)
{
_showErrors = true;
_errors = result.Errors.ToList();
}
else
{
_userCreated = true;
}
}
I feel (yeah, there are a lot of feelings involved) like we still uphold the principle of only one access point by the use of Mediatr. Blazor doesn't need the API, but Angular does.
What would be the right way to go about this?
I am glad you are taking this school project so seriously.
As is with all architectural decisions - "it depends". There is no such thing as a silver bullet approach, only the best for you situation.
I think you both have some points. You are correct in saying you are upholding a single point of access, and thus reducing the amount of code you need to write - but that is not the only thing to consider here. You need to ask yourself a few more questions.
You should treat this as an production application that has the potential to scale
Here are some questions you should ask yourself.
Are the API and the Blazor web server going to be hosted on the same server as the database ?
API's should be stateless, are you going to keep that consideration while writing your blazor web app, since they consume the same code ?
Is your application scalable ? How will you implement things like load balancing on both the API and the blazor web server ?
Can I easily replace/change some in the overall design if needed ?
If I had to choose for you, I would suggest filtering everything through a web API.
Here is why:
You have more options around hosting - you can host your blazor web application on one server and the database/webAPI on another.
It forces developers into "The pit of success". If you have 10 developer working on this product, it's easier for them to think of the application as "one API" rather than an "API and a server that uses the same code". This may not seem important now, but trust me, large scale application can get very hairy very quickly if you don't keep things as simple as possible.
Creating load balancers on Blazor web server can be tricky, since it uses SignalR to communicate with the client.
Testing becomes easier. What if your blazor application has functionality that your Angular client doesn't? That means it would never be built into the web api. Now you need to do things like load testing, stress testing, etc on two separate servers rather than just the web API. The testing required on the Blazor web server would be heavily scaled down if everything ran through the Web API.
And last but not least,the Blazor developers pride themselves on how easy it is to switch between Blazor client and Blazor web server. What if, in future, you decide that Blazor web server isn't the best solution, and you would prefer blazor client ? If everything was running through an Web API this would be a few lines of code. If not - you have a lot of refactoring to do.
I think its a better idea to write a few extra lines to "serialize and deserialize " through an API now, and save yourself potential hassle later.
This is my opinion based off my personal experiences - keep things simple, readable and scalable.
I hope this helped.
Let me know if you would like me to clarify anything.
Happy coding!!
i have a legacy 3rd party application which submits data to our internal sales system. It exposes ASP page with a form to the internet as follows:
<form id="ServiceRequest" enctype="multipart/form-data" method="post" action="AddToServiceRequest.csp">
where AddToServiceRequest.csp is a proprietary IIS handler:
Right now we embed this form into our ASP.Net 4 website using iframe - and that is really inconvenient. What I want to do is to replace this form with a native form, do all validation etc - and then call AddToServiceRequest.csp handler from code-behind logic. What's the right way to do it? I can think only about something like this:
var r = (HttpWebRequest)WebRequest.Create("http://localhost/AddToServiceRequest.csp");
r.Method = "POST";
r.KeepAlive = false;
// fill in form data
var res = r.GetResponse();
res.Close();
but it just does not look "right" to me. Are there any other ways?
If handler serving request is for some other site (from IIS point of view) than code for it will run in separate process or separate AppDomain and you will have no reasonable way to call it directly.
If handler is registered for the same site as yours you may be able to invoke it directly - i.e. if it is APS.Net class that handles request than it just an interface with couple methods - you may be able to instantiate and execute it directly. Note that many handlers depend on HttpContext.Current and you may not be able to set request reasonably for such calls.
It is also unlikely to register same handler to your site as most handlers/controllers/forms are designed to work for particularly configured site (i.e. Web.Config will have DB connection info).
So making direct web request is most straightforward solution. I would not try any other way as most web code will not handle unusual ways of invocation correctly.
You may consider HttpClient instead of WebRequest to get easier async supoprt (assuming .Net 4.5+), but any way of setting up request is ok.
Note that if site uses Windows Authentication you may not be able to pass user information via Web request .
Got a bit of an odd problem. Here goes:
I have two ASP.NET applications: A web app and a web service app.
Information arriving via the webservice effects data in the database used by the web app.
One particular bit of data controls items in a drop down menu - when the data is altered in the app it can call:
HttpContext.Current.Cache.Remove
but I now need to clear the cache in the web service as i can recieve messages which update that information.
Can anyone recommend a way of doing this?
Cache invalidation can be hard. Off the top of my head I can think of 3 solutions of varying complexity which may or may not work for you.
First, you could write a web service for the web app that the web service app calls to invalidate the cache. This is probably the hardest.
Second, you could have the web service app write a "dirty" flag in the database that the web app could check before it renders the drop down menu. This is the route I would go.
Third, you could simply stop caching that particular data.
You could have a web method whose sole purpose is to clear the cache.
var webRequest = HttpWebRequest.Create(clearCacheURL);
var webResponse = webRequest.GetResponse();
// receive the response and return it as function result
var sr = new System.IO.StreamReader(webResponse.GetResponseStream());
var result = sr.ReadToEnd();
Implement the cache with an expiry time.
Cache.Insert("DSN", connectionString, null,
DateTime.Now.AddMinutes(2), Cache.NoSlidingExpiration);
Cache.Insert Method
You can try SQL Dependency. It will trigger an event when the table you have subscribed has any changes.
https://www.codeproject.com/Articles/12335/Using-SqlDependency-for-data-change-events
With our current setup there is a requirement to maintain mirrored sessions between two sites, one existing ASP.NET website hosted in IIS 6.0 which is now containing the new website in an iFrame, and hosted seperately in IIS 7.5 (It's MVC3).
Does anyone have any suggestions as how to keep the parent session in line with the child website session?
My initial thought was to create an ActionFilter to fire a HttpWebRequest to an HTTPHandler of sorts on the parent site on the OnActionExecuting method. There has been doubts raised as to how this would keep the specific sessions inline, perhaps missing knowledge about session ID's of sorts?
Something like:
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
try
{
var request = WebRequest.Create(
ConfigurationManager.AppSettings["HeartbeatURI"]);
using (var webResponse = request.GetResponse())
{
var response = webResponse as HttpWebResponse;
if (response != null && response.StatusCode == HttpStatusCode.OK)
{
Does anyone have any recommendations/ advice here? Thanks!
Update:
After some helpful suggestions I will be investigating whether a solution from the browser, something like:
function setHeartbeat() {
setTimeout("heartbeat()", 300000); // every 5 min
}
function heartbeat() {
$.get(
"http://soemthing:1234/heartbeathandler.ashx",
null,
function(data) {
setHeartbeat();
},
"json"
);
}
Will perform as I require.
There are two fundamental issues your code example is not taking into consideration:
First, sessions are per-client. This solution attempts to 'heartbeat' a single connection from the secondary server. So it won't work.
Second, sessions require client interaction, either via cookies or special, extra URL values. This solution makes no attempt to incorporate those, so no session will be created at all.
EDIT: There's also a third problem: In-process sessions are not guaranteed to stay alive no matter what you do; the application is subject to being recycled at any time, and application recycles will wipe in-process session values. So, you would need to have some external session management system, so that sessions (on both servers) are maintained.
Really, though; it's pretty brittle to try to keep sessions maintained like this. It sounds like it's really important to your application, but there's almost no guarantee it will work all the time. Rearcitecting your application not to require sessions, or to be able to rebuild them on the fly, would be a better option, IMO.