When I use Serve Static Resources with Spring Boot2, my configuration is as follows
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/**").addResourceLocations("classpath:/static/", "classpath:/templates/", "file://temp/report");
super.addResourceHandlers(registry);
}
The project also implements direct access to the image on the hard disk corresponding to the server by accessing the url address http://localhost:8080/demo/123/123_1.png in the browser. The image address on the server is /temp/report/123/123_1.png.
this picture will be returned to the front-end user, the user can see it directly.
Recently, a problem has been found. The program has been running for a while, and now there is a need to update the picture. If a user clicks the picture on the page, the corresponding folder of the server is locked, and When the folder \tmp\report\123 is deleted through the interface, the interface returns an error of Unable to delete directory \tmp\report\123, it seems that the resource has not been released, what is the problem, and is there a corresponding solution?
Related
I'm trying to host my Blazor application on my server.
I spent all the summer on it and I just realized every time I open my website on new device it doesn't create a new session restarting from zero, but continues where I left it. The worst part is there is a login system behind it, so I feel super dumb at the moment.
I really need a big hint on how to fix this "not little" issue.
Is there a way to make server create new session every time someone open the website (without making it loose to other users)?
The solution should be use a Client Template instead, but the performance are really to slow.
UPDATE:
Accounts "user password" are:
- user user
- test test
Download project sample (requires Net Core 3.0)
[SOLUTION] itminus found the solution to my issue.
You have also to add in ConfigureServices in Startup.cs this services.AddScoped<Storage>();
public void ConfigureServices(IServiceCollection services)
{
services.AddRazorPages();
services.AddServerSideBlazor();
services.AddScoped<Storage>();
}
every time I open my website on new device it doesn't create a new session restarting from zero, but continues where I left it.
I checkout your code and find that you're using Singleton Pattern to initialize the Storage. If I understand it correctly, this Storage singleton instance will be shared across different users (also across different devices). As this instance will be used to render the Main.razor page, there will be concurrency problems that you're experiencing now .
To fix that issue, the Storage instance should be limited within some specific connection. As you're using Blazor Server Side, you could register the Storage as a Scoped Service:
In Blazor Server apps, a scoped service registration is scoped to the connection. For this reason, using scoped services is preferred for services that should be scoped to the current user, even if the current intent is to run client-side in the browser.
Firstly, remove the static singleton instance :
public class Storage
{
private static Storage instance;
private Storage()
{
}
public static Storage GetInstance()
{
if (Storage.instance == null)
Storage.instance = new Storage();
return Storage.instance;
}
public List<Items>list {get;set;} = new List<Items>();
public string password {get;set;}
}
Register this Class as a scoped service:
services.AddScoped<Storage>();
And then inject this service in your Login.razor and Main.razor :
#inject project.Storage Storage
Finally, you need change all the Storage.GetInstance(). to Storage.:
Storage.list = Order;
...
Storage.password = password;
I notice that you're also creating the Importer/Additional instance using the Singleton Pattern. I would suggest you should refactor them to use Service Injection in a similar way.
I have created a web API connected to azure sql server in .net core using visual studio for Mac đź’». Then I created a web app in azure and then published by project directly in visual studio for Mac to azure.
After I published I try to access the api using postman and chrome (URL/api/menu) but I got 500 server error which is generic and doesn’t tell me anything.
In visual studio for Mac I got the green light it said published and directly took me to the new url.
So, what do you guys thing is the problem.
This is my first time using azure so I didn’t change any setting or anything
Since many different problems can cause this error page, I can strongly recommend the following in order to determine the root cause quickly and easily, without struggling with Azure (or any server/platform for that matter) to get logs.
You can enable extremely helpful error messages at startup by setting the .UseSetting("detailedErrors", "true") and .CaptureStartupErrors(true) actions in your Program.cs file.
For ASP.NET CORE 2.1
public class Program
{
public static void Main(string[] args)
{
BuildWebHost(args).Run();
}
public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.CaptureStartupErrors(true)
.UseSetting("detailedErrors", "true")
.UseStartup<Startup>()
.Build();
}
Add these commands in your startup.cs class:
app.UseDeveloperExceptionPage();
app.UseDatabaseErrorPage();
app.UseBrowserLink();
also enable stdoutLog in your web.config file
stdoutLogEnabled="true" stdoutLogFile=".\logs\stdout"
Error code 500 in web api,usually, means problems with a configuration in Startup.cs - the most common problems include an issue with DB itself, an issue with migrations (if you are using Code First approach), problems with appsettings.js.
Please refer to the log file in .\logs\stdout.
Hope it helps.
As part of my application, I'm saving a dynamically generated list of png files in "/build/test-results/output/png/zpl-1.png". In the html page, I have used all the following:
<img src="/zpa/images/zpl-1.png" >
Works, but my saved images don't store in this location.
Path: <img src="/zpa/build/resources/main/static/images/zpl-1.png" >
Not loading (error 404)
Absolute path: <img src="file:///Users/sasi-kathimanda/STS/printing-agent/build/resources/main/static/images/zpl-1.png" >
Not loading.
My configuration:
server:
port: 8090
contextPath: /zpa
although i have tagged this question as "spring boot",probably i was missing it in the title may causes the confusion.
so here is how i solved it, the problem lies in configuring the static web resources in the spring boot config.
#Configuration
public class StaticResourceConfiguration extends WebMvcConfigurerAdapter {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/pngFiles/**")
.addResourceLocations("file:ext-resources/")
.setCachePeriod(0);
}
and in my index.html using <img src="/zpa/pnFiles/zpl-1.png"> works.
Those paths are server file paths and would only work on the local machine (the machine that host the files).
You either need to move the upload directory to somewhere on the public side of the server (ie in the document root) and use a relative path
or
You will need a server side script that can fetch the images from a directory outside the document root and server them as an image.
You can use relative links (with no slash at the beginning) to make the image paths relative to the HTML file that you are including the images in. All three links that you showed are absolute paths.
Relative paths are helpful when you don't know where you are going to be serving the files from, such as when you're just viewing the HTML file instead of actually using a server.
For example, if your HTML file is in the zpa folder,
<img src="build/resources/main/static/images/zpl-1.png" >
**Outside server call image file using Spring Boot**
public class StaticResourceConfiguration extends WebMvcConfigurerAdapter{
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
String filePath = "E:/AshokParmar/Project/imges/";
registry.addResourceHandler("/img/qrcode/**")
.addResourceLocations("file:/"+filePath)
.setCachePeriod(0);
}
}
**in html file use below tags it works**
<img src="<c:url value="/img/qrcode/0012340012.png" />"/>
Dears,
I have followed the below steps to resolve the issue.
Steps:
1. My Apache Tomcat 9.0 server installed location is D:\apache-tomcat-9.0.8\apache-tomcat-9.0.8
2. I have created "images" folder under the "webapps" folder in Tomcat installed folder.
Hence my folder structure is "D:\apache-tomcat-9.0.8\apache-tomcat-9.0.8\webapps\images".
3. Then I have cleared my browser history and run the application. Now images are loading succesufully...
I will appreciate any help on steps for an implementation to switch an MVC3/Razor Web Application to offline mode for maintenance. At the offline mode only a static page could be seen by the public but an administrator who is logged in should be able to view, browse and update the site fully. Ideally I want the web administrator just to tick on a value at the administrative back-end which will be registered in the database.
You could simply check some condition within BeginRequest in Global.asax.
protected void Application_BeginRequest()
{
if (myDb.SiteIsOffline && !CurrentUserIsAdministrator())
Response.Redirect("~/offline.html");
}
I have Visual Studio 2010 solution with an Azure Service and an ASP.NET MVC 3 solution that serves as a Web Role for the Azure service. No other roles attached to the service other than that.
Every deployment to the Azure staging (or production, for that matter) environment takes up to 20 minutes to complete, form the moment I click publish on Visual Studio until all instances (2) are started.
As you can imagine this makes it a PITA to publish often, or to quick-fix some bugs. Is there a way to speed the process up? Would it be faster to upload the package to de Blob storage and upgrade from there? How would I go about achieving that?
I feel on-line docs on Azure leave a lot to be desired. Particularly when it comes to troubleshooting by the way.
Thanks.
One idea for reducing the need (and frequency) for redeploying is to move static content into blob storage, external to the package. For instance, move your css and javascript to blob storage, along with images. Once this is done, you'd only have to recompile / redeploy for .NET code changes. You can upload updated css, at any time, to blob storage. If you want to test this in staging first, you could always have a staging vs. production container name for your static content and store that container name in a config setting.
This doesn't change the deployment time when you do need to redeploy, but at least you can reduce how often you go through that process...
You should enable Web Deploy in your Azure project. It works this way :
1/ Create a RDP account (don't forget, you need to upload a certificate with its private key so that Azure can decipher the password). That is hidden in the Deploy Dialog Box for your Azure deployment project.
2/ Enable Web Deployment - same place
Once you've published the app that way, right-click in the web application (not the azure deployment project) and select Publish. The pop-up has everything defined except the password, enter that as well and you'll upload your changes to Azure in a matter of seconds.
CAVEAT : this is meant for single-instance web apps, definitely not the way to go for a production upgrade strategy, and the Blob storage answer already mentioned is the best option in that case.
Pierre
My solution to this problem is only to push a new package when I am changing code in the RoleEntryPoint or with the Service Definition. In Azure 1.3 you now have the ability to use Remote Desktop Connection. Using RDC, I will compile my code locally and use copy/paste to place it on the Azure server in the appropriate directory. Once the production code is running correctly, I can then push the fully tested version to staging and then do a VIP swap. This limits the number of times I actually have to deploy a package.
You actually have quite a long window in which you can keep modifying your code in Azure before you have to publish a new package. The new package is only really needed for those cases where Azure has to shutdown/restart your role instance.
It's a nice idea to try uploading your project to blob storage first, but unfortunately this is what Visual Studio is doing for you behind the scene anyway. As has been pointed out elsewhere, most of the time in doing the deploy is not the upload itself, but the stopping and starting of all of your update domains.
If you're just running this site in a development environment, then the only way I know to speed it up is to run just one instance. If this is the live environment, then... sorry, I think you're out of luck.
So that I don't have to deploy to the cloud to test minor changes, what I've found works quite well is to engineer the site so that it works when running in local IIS just like any other MVC site.
The biggest barrier to this working are settings that you have in the cloud config. The way we get around this is to make a copy of all of the settings in your cloud config and put them in your web.config in the appSettings. Then rather than using RoleEnvironment.GetConfigurationSettingValue() create a wrapper class that you call instead. This wrapper class checks RoleEnvironment.IsAvailable to see if it is running in the Azure fabric, if it is, it calls the usual config function above, if not, it calls WebConfigurationManager.AppSettings[].
There are a few other things that you'll want to do around getting the config setting change events which hopefully you can figure out from the code below:
public class SmartConfigurationManager
{
private static bool _addConfigChangeEvents;
private static string _configName;
private static Func<string, bool> _configSetter;
public static bool AddConfigChangeEvents
{
get { return _addConfigChangeEvents; }
set
{
_addConfigChangeEvents = value;
if (value)
{
RoleEnvironment.Changing += RoleEnvironmentChanging;
}
else
{
RoleEnvironment.Changing -= RoleEnvironmentChanging;
}
}
}
public static string Setting(string configName)
{
if (RoleEnvironment.IsAvailable)
{
return RoleEnvironment.GetConfigurationSettingValue(configName);
}
return WebConfigurationManager.AppSettings[configName];
}
public static Action<string, Func<string, bool>> GetConfigurationSettingPublisher()
{
if (RoleEnvironment.IsAvailable)
{
return AzureSettingsGet;
}
return WebAppSettingsGet;
}
public static void WebAppSettingsGet(string configName, Func<string, bool> configSetter)
{
configSetter(WebConfigurationManager.AppSettings[configName]);
}
public static void AzureSettingsGet(string configName, Func<string, bool> configSetter)
{
// We have to store these to be used in the RoleEnvironment Changed handler
_configName = configName;
_configSetter = configSetter;
// Provide the configSetter with the initial value
configSetter(RoleEnvironment.GetConfigurationSettingValue(configName));
if (AddConfigChangeEvents)
{
RoleEnvironment.Changed += RoleEnvironmentChanged;
}
}
private static void RoleEnvironmentChanged(object anotherSender, RoleEnvironmentChangedEventArgs arg)
{
if ((arg.Changes.OfType<RoleEnvironmentConfigurationSettingChange>().Any(change => change.ConfigurationSettingName == _configName)))
{
if ((_configSetter(RoleEnvironment.GetConfigurationSettingValue(_configName))))
{
RoleEnvironment.RequestRecycle();
}
}
}
private static void RoleEnvironmentChanging(object sender, RoleEnvironmentChangingEventArgs e)
{
// If a configuration setting is changing
if ((e.Changes.Any(change => change is RoleEnvironmentConfigurationSettingChange)))
{
// Set e.Cancel to true to restart this role instance
e.Cancel = true;
}
}
}
The uploading itself takes a bit more than a minute most of the time. It's the starting up of the instances that take up most of the time.
What you can do is to deploy your fixes to staging first (note that it costs money so don't let it be there for too long). Swapping from staging to production only takes a couple of seconds. So while your application's still running you can upload the patched version, let your testers test it on staging and when they give the go then simply swap it to production.
I haven't tested your possible alternative approach by first uploading to blob storage first. But I think that's overhead as it doesn't speed up starting up the instances.