On an ASP.NET Core view using AngularJs I have:
<div ng-include="'/views/profile.html'" ng-controller="ProfileController as c"></div>
When I change the HTML file and run the application its content does not change.
I checked it and the HTML file is cached ...
How can I avoid the caching of angular HTML templates in ASP.NET Core?
Actually this solution, I have got originally from the replies at the link given by #Deblaton in the comment here.
But, I modified for the purpose of ours'...
Just for development environment I disabled cache for only the HTML templates in the Configure() method of ASP.Net Core Request pipeline,
if (env.IsDevelopment())
{
app.UseStaticFiles(new StaticFileOptions()
{
OnPrepareResponse = (context) =>
{
if (context.File.Name.ToLower().EndsWith(".html"))
{
context.Context.Response.Headers["Cache-Control"] = "no-cache, no-store";
context.Context.Response.Headers["Pragma"] = "no-cache";
context.Context.Response.Headers["Expires"] = "-1";
}
}
});
}
else
{
app.UseStaticFiles();
}
And it just did the work!
Related
I am using webview_flutter with version 3.0.0 in my app. I have heavy usage of two-way communication between flutter and javascript. Everything works on debug mode nicely. But, after I build the APK started to get some errors in the javascript channel. I tried with flutter run --release and got the same error.
In my web application (ReactJs), I am using channels in this way:
index.html
<div id="root">
<script>
function sendToFlutter(message) {
if (flutterChannel) {
flutterChannel.postMessage(message);
}
}
</script>
</div>
calling is from React component like this:
window.sendToFlutter("hello-world");
My Webview setup from Flutter end:
Completer<WebViewController> webViewCompleter = Completer<WebViewController>();
WebView(
debuggingEnabled: false,
initialUrl: "https://example.com",
javascriptMode: JavascriptMode.unrestricted,
onWebViewCreated: (WebViewController webViewController) {
webViewCompleter.complete(webViewController);
},
javascriptChannels: <JavascriptChannel>{
JavascriptChannel(
name: "flutterChannel",
onMessageReceived: (JavascriptMessage message) {
if (message.message == "hello-world") {
// Do something
}
})
},
navigationDelegate: (NavigationRequest request) {
if (request.url.startsWith('https://www.youtube.com/')) {
return NavigationDecision.prevent;
}
return NavigationDecision.navigate;
},
gestureNavigationEnabled: true,
zoomEnabled: false,
userAgent: Platform.isAndroid ? kAndroidUserAgent : kIosUserAgent,
);
When I call the channel from ReactJs, then I am getting this error:
TypeError: flutterChannel.postMessage is not a function
According to alexbatalov's research in https://github.com/flutter/flutter/issues/92548, the current workaround is to do the following:
Create android/app/proguard-rules.pro. At minimum you need to have a
rule for JavascriptInterface, but I recommend to copy entire
proguard-android.txt, given the fact that you don’t have these rules.
# Preserve annotated Javascript interface methods.
-keepclassmembers class * {
#android.webkit.JavascriptInterface <methods>;
}
After installing the React app template from .NET Core 3.1 using dotnet new react the application works perfectly in Development and Production. The problem appears when trying to use Swagger or Hangfire dashboard endpoints.
After the app is created I add the package reference for Hangfire and for practical purposes the memory storage:
<PackageReference Include="Hangfire" Version="1.7.*" />
<PackageReference Include="Hangfire.MemoryStorage" Version="1.7.0" />
In Startup.cs:
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
services.AddHangfire(config =>
config.SetDataCompatibilityLevel(CompatibilityLevel.Version_170)
.UseSimpleAssemblyNameTypeSerializer()
.UseDefaultTypeSerializer()
.UseMemoryStorage());
services.AddHangfireServer();
// In production, the React files will be served from this directory
services.AddSpaStaticFiles(configuration =>
{
configuration.RootPath = "ClientApp/build";
});
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment 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.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapHangfireDashboard();
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller}/{action=Index}/{id?}");
});
app.UseSpa(spa =>
{
spa.Options.SourcePath = "ClientApp";
if (env.IsDevelopment())
{
spa.UseReactDevelopmentServer(npmScript: "start");
}
});
}
After publishing the application and run it, the app works fine except the Hangfire dashboard, and trying to access the route: /Hangfire causes the server return the SPA index.html
But if I refresh the page doing a hard reload, the dashboard loads fine.
Same thing occurs with Swagger.
Can someone give me a hand ?
After following Guilherme suggestion, unregistering the service worker solved the issue. Instead of ignoring the routes, I opted to unregister it.
Thank you very much !
I have a Django CMS that serves as my back-end application. And I'm trying to create pages dynamically in my Gatsby front-end site. My Django application is exposed over GraphQL using Graphene. But I'm not able to query the slugs from backend CMS and create pages using gatsby-node.js. How do I create pages when I create a page in the back-end application?
The idea being
//gatsby-node.js
exports.createPages = ({ graphql, actions }) => {
const pages = graphql`
{
blogPages{
edges{
node{
slug // this slug supposed to come from the backend CMS (Atleast i think)
}
}
}
}
`;
const { createPage } = actions
const blogTemplate = path.resolve(`src/templates/blogTemplate.js`);
pages.blogPages.edges.forEach(edge => { //this should help to create dynamic pages - slug coming from backend CMS
const slug = edge.node.blogpage.slug;
createPage({
path: slug,
component: blogTemplate
})
})
}
It's been said in the comments already, but just to summarize: since Gatsby is a static site generator you cannot dynamically add pages at runtime. Each page corresponds to its own html file that needs to be created on your webserver. That is not something you can do at runtime.
What you can do is to set up a continuous integration workflow where you have a build running in the cloud somewhere. Trigger it when you make a change in Django, or alternatively run it regularly (hourly/daily) to update the site.
If running a rebuild does not work for your use case you need to look at an entirely different architecture.
I am currently working with React and SignalR. I am using .Net Core 2.1 and the Microsoft.AspNetCore.App package to get the recent SignalR. I have installed #aspnet/signalr as well and I keep getting a 404 error because it is still attempting to go to the /negotiate endpoint which I know it doesn't use anymore. I have confirmed I am up to date on on all packages. Any pointers on where I should be going?
const hubConnection = new HubConnectionBuilder().withUrl('http://localhost:3000/ChatHub').build();
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
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.AddCors(o => o.AddPolicy("CorsPolicy", builder =>
//{
// builder
// .AllowAnyMethod()
// .AllowAnyHeader()
// .WithOrigins("http://localhost:3000");
//}));
services.AddSignalR();
//services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
// In production, the React files will be served from this directory
services.AddSpaStaticFiles(configuration =>
{
configuration.RootPath = "ClientApp/build";
});
}
// 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");
app.UseHsts();
}
//app.UseCors("CorsPolicy");
app.UseFileServer();
app.UseSignalR(routes =>
{
routes.MapHub<ChatHub>("/ChatHub");
});
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");
}
});
}
I keep getting a 404 error because it is still attempting to go to the /negotiate endpoint which I know it doesn't use anymore
ASP.NET Core SignalR definitely still uses the /negotiate endpoint. In the previews, we used an OPTIONS request instead but that caused a lot of problems so we went back to the /negotiate endpoint.
It looks like you're using a "development server" (spa.UseReactDevelopmentServer in your Startup). That usually means that the development server is serving up your HTML/JS content from a different server than your ASP.NET Core app is running on (rather than just being static files served by the ASP.NET Core app). If that's the case, you need to reference the ASP.NET Core server using a full URL when you connect.
This is because your HTML/JS content is being served by the development server at http://localhost:X but your ASP.NET Core server is running at http://localhost:Y. So when you use /ChatHub as a URL, the browser interprets that as http://localhost:X/ChatHub, so you aren't hitting your ASP.NET Core app (with the SignalR server) but rather then dev server, which has no content at that URL and produces a 404.
namespace MyQuotesApp
{
public class Startup
{
// This method gets called by the runtime. Use this method to add services to the container.
// For more information on how to configure your application, visit http://go.microsoft.com/fwlink/?LinkID=398940
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
loggerFactory.AddConsole();
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseDefaultFiles();
app.UseStaticFiles();
//app.Run(async (context) =>
//{
// await context.Response.WriteAsync("Hello World!");
//});
app.UseMvc();
}
}
}
UseDefaultFiles pick these files by default.
default.htm
default.html
index.htm
index.html
If that not worked in your case. You can specify name of your default file with DefaultFilesOptions.
DefaultFilesOptions options = new DefaultFilesOptions();
options.DefaultFileNames.Clear();
options.DefaultFileNames.Add("index.html");
app.UseDefaultFiles(options);
You can also use app.UseFileServer();, it combines the functionality of
app.UseDefaultFiles();
app.UseStaticFiles();
Note: UseDefaultFiles must be called before UseStaticFiles to serve the default file. UseDefaultFiles is a URL re-writer that doesn't actually serve the file. You must enable the static file middleware (UseStaticFiles) to serve the file.
P.S. also update your packages to most latest.
Try this.
app.UseMvc(config =>
{
config.MapRoute(
name: "Default",
template: "{controller=*YourControllerName*}/{action=Index}/{id?}"
);
});