I'm trying to resize images using Imageflow's query string API in my .net core application.
I have installed Imageflow.Server.
My Configure Method looks like this:
public void Configure(IApplicationBuilder App, IWebHostEnvironment Env)
{
if (AppSettings.IsDevelopment)
{
App.UseDeveloperExceptionPage();
}
else
{
App.UseExceptionHandler(Options =>
{
App.UseExceptionHandler("/error/404/");
});
App.UseHsts();
}
App.UseImageflow(new ImageflowMiddlewareOptions()
.SetMapWebRoot(false)
.MapPath("/upload/", "{upload folder path}"));
App.UseFileServer();
App.UseRouting();
App.UseSession();
App.UseEndpoints(Endpoints =>
{
Endpoints.MapControllers();
});
}
There is no problem on localhost or if the upload folder is inside the wwwroot folder, but if upload folder is outside the app root directory then images won't resize.
Any Ideas how can I solve this problem?
If you have registered the folder as a virtual directory, IIS will prevent ASP.NET Core from serving or resizing those files.
Unmap the virtual directory in IIS and use ASP.NET Core instead.
To allow ASP.NET Core to serve files, call UseStaticFiles a second time to map that virtual directory: https://learn.microsoft.com/en-us/aspnet/core/fundamentals/static-files?view=aspnetcore-3.1
You'll also still want to call MapPath on ImageflowMiddlewareOptions for the same virtual directory.
This could be a permissions issue. If on-disk permissions do not allow the user account running the app to access the folder, it will fail.
Related
I am new to VueJS and SPAs in general. I have created a new ASP Core site with a WebAPI controller for data and a VueJS front end. I am now trying to deploy this site to IIS and I am not sure how to do it correctly. I created a new application in IIS with an application pool set to "no-managed-code" and set the physical location to the VueJS app /dist folder. The site is loading, but I'm getting 404's for all of my service calls. I assume this is because the root of the site is set to the VueJS app folder instead of the root of the ASP Core folder. How do I set this up correctly to serve my app from myServer/mySite and also have my service endpoints as myServer/mySite/api/myController/myAction?
Scenario: Your dotnet core app has the API endpoints and you want to host the client site SPA on the same site. API calls will go through to the dotnet app and any other request will serve the index.html of the SPA.
.NET core supports this scenario with the methods from Microsoft.AspNetCore.SpaServices namespace like UseSpa()
Also note that in .NET 5 these extensions are moving to separate package Microsoft.AspNetCore.SpaServices.Extensions. It is available now but not well documented.
Your build SPA should go in ClientApp/dist in this example
e.g.
using Microsoft.AspNetCore.SpaServices;
public class Startup
{
// ...
public void ConfigureServices(IServiceCollection services)
{
// In production, the SPA files will be served from this directory
services.AddSpaStaticFiles(configuration =>
{
configuration.RootPath = "ClientApp/dist";
});
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
// ...
app.UseStaticFiles();
app.UseSpaStaticFiles();
app.UseMvc();
// Must be near the end of the method because
// it will send any unhandled requests to index.html for SPA
app.UseSpa(spa =>
{
spa.Options.SourcePath = "ClientApp";
if (env.IsDevelopment())
{
// Development requests are send through to local node server
spa.UseProxyToSpaDevelopmentServer("http://localhost:8080/");
}
});
}
}
I'm building a web application using ASP.NET Core 3.1. By default, the wwwroot directory is the default web root directory.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseStaticFiles(); // defaults to wwwroot
}
It can be changed to any directory including the project root
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseStaticFiles(new StaticFileOptions
{
FileProvider = new Microsoft.Extensions.FileProviders.PhysicalFileProvider(System.IO.Directory.GetCurrentDirectory()) // serves static files from the project root
});
}
Having the project root as my web root would suit my current project structure. Is there a good reason why I shouldn't use the project root as the web root?
After some flawed testing (see comments under the answer) it turns out there is a very good reason not to do this. Your appsettings.json file will be available to anyone who wants it.
Summary:
I have a .NET Core project that uses the React web app template for the front end. This app uses Entity Framework Core to connect to an Azure SQL Database. I used the Db-Scaffold command to generate my models (just one table at the moment), and created a controller to return this table. Locally, this works fine and the table (JSON) is returned at localhost/api/Users. However when I deploy the website to Azure (CD pipeline is VS 2017 - > GitHub -> DockerHub -> Azure Web App), navigating to mysite.azurewebsites.net/api/Users just renders the login page (React) of my app.
Attempts:
I have tried:
Adding a connection string as a shared value in Azure (named DefaultConnection)
Adding all the outbound IP's of the Azure Web App to the Azure SQL Whitelist
Running the following in the consoles of the web app
fetch('api/users')
This just returns:
Failed to load resource: the server responded with a status of 500 (Internal Server Error)
I have also tried changing database values and refreshing the local version to make sure it was not just a cached page and sure enough the changes were reflected locally.
I also set ASPNETCORE_ENVIRONMENT in the Web App settings in Azure to Production. Although when I go to the error message, page (through the console) I get this:
<h1 class="text-danger">Error.</h1>
<h2 class="text-danger">An error occurred while processing your request.</h2>
<p>
<strong>Request ID:</strong> <code>0HLK3RLI8HD9Q:00000001</code>
</p>
<h3>Development Mode</h3>
<p>
Swapping to the <strong>Development</strong> environment displays detailed information about the error that occurred.
</p>
<p>
<strong>The Development environment shouldn't be enabled for deployed applications.</strong>
It can result in displaying sensitive information from exceptions to end users.
For local debugging, enable the <strong>Development</strong> environment by setting the <strong>ASPNETCORE_ENVIRONMENT</strong> environment variable to <strong>Development</strong>
and restarting the app.
</p>
Code
UsersController.cs
[Route("api/[controller]")]
public class UsersController : Controller
{
private readonly AccrubalanceDbContext _context;
public UsersController(AccrubalanceDbContext context)
{
_context = context;
}
// GET: api/values
[HttpGet]
public async Task<IEnumerable<Users>> Get()
{
return await _context.Users.ToListAsync();
}
appsettings.json
{
"ConnectionStrings": {
"DefaultConnection":<MyConnectionStringGoesHere>
},
index.js (just in case React might be the routing problem)
const baseUrl = document.getElementsByTagName('base')
[0].getAttribute('href');
const rootElement = document.getElementById('root');
ReactDOM.render(
<BrowserRouter basename={baseUrl}>
<App />
</BrowserRouter>,
rootElement);
registerServiceWorker();
Startup.cs (could be potentially problem with HTTP routing in Prod?)
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
// In production, the React files will be served from this directory
services.AddSpaStaticFiles(configuration =>
{
configuration.RootPath = "ClientApp/build";
});
services.AddDbContext<AccrubalanceDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseSpaStaticFiles();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller}/{action=Index}/{id?}");
});
app.UseSpa(spa =>
{
spa.Options.SourcePath = "ClientApp";
if (env.IsDevelopment())
{
spa.UseReactDevelopmentServer(npmScript: "start");
}
});
}
Conclusion
In conclusion, I need this API call to work within the hosted Azure Web App like it does on my local machine. I know I am close since I got it to work locally, but I am missing something along the way to Azure. Any help or pointers you can provide would be great :)
I am still new to SO and took my time to do my best to format this correctly. I am open to constructive formatting critiques and suggestions to help me improve.
Edit:
As I mentioned before, I am using docker for CD/CI. So I ran my docker container locally and the api does not work there either. Docker throws this warning in the command window when I navigate to the apps home page.
warn: Microsoft.AspNetCore.HttpsPolicy.HttpsRedirectionMiddleware[3]
Failed to determine the https port for redirect.
Edit 1 Determination
I also found this article which points to react routing being an issue. I have looked in Kudo in my Azure app and I do not have a web.config. Could potentially try adding on but I do not have the regular Windows UI since my app is a Linux server.
The container build acts like the Azure App does, may not be an Azure issue. Still unsure why docker is acting differently than running in VS.
Solution:
There is obviously some problem with Docker. Since it was becoming more of a headache then a help, I removed it from the deployment pipeline and just followed the instructions here. Once I did this deployment method, all the API's worked. Only downside is I had to make a new app in Azure.
I have set up an empty WebAPI project with .NET Core rc2 and have it wired up with Angular2 rc1. Angular will handle everything view related and the WebAPI is the backend.
When I start the app by default it comes up with localhost:4578/api/values from the default API controller as startpage.
However, I want it to show index.html by default which is located in wwwroot and is hosting my Angular2 app.
In Startup.cs the Configure method looks like this:
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
loggerFactory.AddConsole(Configuration.GetSection("Logging"));
loggerFactory.AddDebug();
app.UseDefaultFiles();
app.UseStaticFiles();
app.UseMvc();
app.Run(ctx =>
{
ctx.Response.Redirect("/index.html");
return Task.FromResult(0);
});
}
app.UseStaticFiles and the app.Run lambda need to be in place for the manual redirect to index.html to work but it still comes up with /api/values as default start page.
I know that for debugging purposes I can change the start page easily but I want to change it such that when I host it it always serves index.html as start page.
How can I change this?
When creating a new empty WebAPI project, the launchsettings.json file points to api/values by default. To change it, go to the launchsettings.json file in your project:
and change the launchUrl value to: http://localhost:4578 (from http://localhost:4578/api/values).
I'm developing a very simple SPA style application and I don't want to use razor, so I just need it to serve up HTML files (from the wwwroot folder), except for when the js calls my API controllers. In Web API 2 you could get the router to ignore HTML files so they are served directly e.g.
config.Routes.IgnoreRoute("Html", "{whatever}.html/{*pathInfo}");
similar to this example: http://www.strathweb.com/2014/04/ignoring-routes-asp-net-web-api/ is the IgnoreRoute functionality just not implemented or has it been changed?
At the moment if I have app.UseMvc(); in my Startup.cs any get request to "/" gets me this exception:
An unhandled exception occurred while processing the request.
InvalidOperationException: The view 'Index' was not found. The following locations were searched:
/Views/Home/Index.cshtml
/Views/Shared/Index.cshtml.
Microsoft.AspNet.Mvc.Rendering.ViewEngineResult.EnsureSuccessful()
But when I leave it without MVC it serves up the index.html file when you request "/" - obviously my API controllers won't work then though.
I think if you want to serve index.html even when your MVC option is enabled? If so you have to change one setting.
When you enable MVC there is a default route added to search for Home/Index when your url is like http://localhost:yourport.
When you disable MVC it will serve index.html as no route is present in that case.
So if you want to serve index.html when MVC is enabled then add the following in Configure function before using MVC.
app.UseDefaultFiles(new Microsoft.AspNet.StaticFiles.DefaultFilesOptions() { DefaultFileNames = new[] { "index.html" } });
// your UseMVC goes here.
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseDefaultFiles();
app.UseStaticFiles();
app.UseMvc();
}