I'm working on an ASP.NET webforms and I put this code in my web.config :
<httpCompression directory="%SystemDrive%\inetpub\temp\IIS Temporary Compressed Files">
<scheme name="gzip" dll="%Windir%\system32\inetsrv\gzip.dll"/>
<dynamicTypes>
<add mimeType="text/*" enabled="true"/>
<add mimeType="message/*" enabled="true"/>
<add mimeType="application/javascript" enabled="true"/>
<add mimeType="application/x-javascript" enabled="true"/>
<add mimeType="*/*" enabled="false"/>
</dynamicTypes>
<staticTypes>
<add mimeType="text/*" enabled="true"/>
<add mimeType="message/*" enabled="true"/>
<add mimeType="application/javascript" enabled="true"/>
<add mimeType="application/x-javascript" enabled="true"/>
<add mimeType="*/*" enabled="false"/>
</staticTypes>
</httpCompression>
<urlCompression doStaticCompression="true" doDynamicCompression="true"/>
Sometimes Google Page Speed Insights and PageSpeed extension on Chrome don't say the same message about enable compression. Sometimes there are about 10 files so it's high importance, sometimes it's just 4 files, so medium importance... Sometimes Mobile version shows 10 files while computer version shows 4. It seems to be random. For instance. I analyse at 11:00 it's not the same at 11:30 and not the same at 13:00... Can change everytime without data or code changes.
Can someone explain this strange thing ?
By the way, I don't know why among the 4 remaining files, there are still a css file and a js file not "enabled" since other css and js files are not in the list anymore.
I also would like to remove the WebResource.axd?d=...&t=... from the 4 remaining files on some pages. That's why I added a mimeType x-javascript. But it doesn't seem to work.
Thanks.
here what you should do:
1. Enable dynamic compression in IIS7 enable compression
2. Enable page compression by using this code:
public static bool IsGZipSupported()
{
string AcceptEncoding = HttpContext.Current.Request.Headers[«Accept-Encoding»];
if (!string.IsNullOrEmpty(AcceptEncoding) &&
(AcceptEncoding.Contains(«gzip») || AcceptEncoding.Contains(«deflate»)))
return true;
return false;
}
public static void GZipEncodePage()
{
if (IsGZipSupported())
{
HttpResponse Response = HttpContext.Current.Response;
string AcceptEncoding = HttpContext.Current.Request.Headers[«Accept-Encoding»];
if (AcceptEncoding.Contains(«gzip»))
{
Response.Filter = new System.IO.Compression.GZipStream(Response.Filter,
System.IO.Compression.CompressionMode.Compress);
Response.AppendHeader(«Content-Encoding», «gzip»);
}
else
{
Response.Filter = new System.IO.Compression.DeflateStream(Response.Filter,
System.IO.Compression.CompressionMode.Compress);
Response.AppendHeader(«Content-Encoding», «deflate»);
}
}
}
protected void Page_Load(object sender, EventArgs e)
{
HtmlUtil.GZipEncodePage();
}
Enable static content enable static content
Related
Crystal Report......Web Application MVC
I am trying to get Image to displayed.
Logo of company instead it is showing image alt="Image". By checking inspecting element I came to know that the src="CrystalImageHandler.aspx?dynamicimage=cr_tmp_image_d6cbdac3-0385-4ffd-a368-5a514303cb66.png"
. I tried hard to get it rectified by searching on many sites but could get...
any one who know this issue...
Thanks
Hi I have struggled with similar issue for quite some time.
I hope this solution might help you.
Web Config Changes:
<httpHandlers>
<add verb="GET" path="CrystalImageHandler.aspx" type="CrystalDecisions.Web.CrystalImageHandler, CrystalDecisions.Web, Version=13.0.3500.0, Culture=neutral, PublicKeyToken=692FBEA5521E1304" />
</httpHandlers>
<handlers>
<remove name="CrystalImageHandler.aspx_GET" />
<add name="CrystalImageHandler.aspx_GET" verb="GET" path="CrystalImageHandler" type="CrystalDecisions.Web.CrystalImageHandler, CrystalDecisions.Web, Version=13.0.3500.0, Culture=neutral, PublicKeyToken=692FBEA5521E1304" preCondition="integratedMode"/>
</handlers>
Note*: Handler Path field didn't had ".aspx" extension.
Add this block of code to you global.asax.cs
protected void Application_BeginRequest(object sender, EventArgs e)
{
var p = Request.Path.ToLower().Trim();
if (p.EndsWith("/crystalimagehandler.aspx") && p != "/crystalimagehandler.aspx")
{
var fullPath = Request.Url.AbsoluteUri.ToLower();
var NewURL = fullPath.Replace(".aspx", "");
Response.Redirect(NewURL);
}
}
This would Help you to resolve the issue.
In previous versions all of these settings could be added and tweaked in the Web.Config file using something like the code below:
<staticContent>
<mimeMap fileExtension=".webp" mimeType="image/webp" />
<!-- Caching -->
<clientCache cacheControlMode="UseMaxAge" cacheControlMaxAge="96:00:00" />
</staticContent>
<httpCompression directory="%SystemDrive%\inetpub\temp\IIS Temporary Compressed Files">
<scheme name="gzip" dll="%Windir%\system32\inetsrv\gzip.dll" />
<dynamicTypes>
<add mimeType="text/*" enabled="true" />
<add mimeType="message/*" enabled="true" />
<add mimeType="application/javascript" enabled="true" />
<add mimeType="*/*" enabled="false" />
</dynamicTypes>
<staticTypes>
<add mimeType="text/*" enabled="true" />
<add mimeType="message/*" enabled="true" />
<add mimeType="application/javascript" enabled="true" />
<add mimeType="*/*" enabled="false" />
</staticTypes>
</httpCompression>
<urlCompression doStaticCompression="true" doDynamicCompression="true"/>
However, with the Web.Config no longer being around in ASP.NET vNext, how do you adjust settings like this? I have searched the net and the ASP.NET Github repo, but not come across anything - any ideas?
As "agua from mars" states in the comments, if you're using IIS you can use IIS's static file handling, in which case you can use the <system.webServer> section in a web.config file and that will work as it always did.
If you're using ASP.NET 5's StaticFileMiddleware then it has its own MIME mappings that come as part of the FileExtensionContentTypeProvider implementation. The StaticFileMiddleware has a StaticFileOptions that you can use to configure it when you initialize it in Startup.cs. In that options class you can set the content type provider. You can instantiate the default content type provider and then just tweak the mappings dictionary, or you can write an entire mapping from scratch (not recommended).
ASP.NET Core - mime mappings:
If the extended set of file types you are providing for the entire site are not going to change, you can configure a single instance of the ContentTypeProvider class, and then leverage DI to use it when serving static files, like so:
public void ConfigureServices(IServiceCollection services)
{
...
services.AddInstance<IContentTypeProvider>(
new FileExtensionConentTypeProvider(
new Dictionary<string, string>(
// Start with the base mappings
new FileExtensionContentTypeProvider().Mappings,
// Extend the base dictionary with your custom mappings
StringComparer.OrdinalIgnoreCase) {
{ ".nmf", "application/octet-stream" }
{ ".pexe", "application/x-pnal" },
{ ".mem", "application/octet-stream" },
{ ".res", "application/octet-stream" }
}
)
);
...
}
public void Configure(
IApplicationBuilder app,
IContentTypeProvider contentTypeProvider)
{
...
app.UseStaticFiles(new StaticFileOptions() {
ContentTypeProvider = contentTypeProvider
...
});
...
}
I trying to configure httpCompression on IIS7. By googling, I found that it can be made using httpCompression section in config. The problem, that I can't make it work from web.config.
When I make the configuration in applicationHost.config everything works as needed, but I want to be able to make this configuration per application and not globally.
I changed section definition in applicationHost.config to <section name="httpCompression" overrideModeDefault="Allow" /> and moved httpCompression section to web.config:
<httpCompression directory="%SystemDrive%\inetpub\temp\IIS Temporary Compressed Files">
<scheme name="gzip" dll="%Windir%\system32\inetsrv\gzip.dll" />
<staticTypes>
<add mimeType="text/*" enabled="true" />
<add mimeType="message/*" enabled="true" />
<add mimeType="application/x-javascript" enabled="true" />
<add mimeType="application/atom+xml" enabled="true" />
<add mimeType="application/xaml+xml" enabled="true" />
<add mimeType="*/*" enabled="false" />
</staticTypes>
<dynamicTypes>
<add mimeType="text/*" enabled="true" />
<add mimeType="message/*" enabled="true" />
<add mimeType="application/x-javascript" enabled="true" />
<add mimeType="application/json" enabled="true" />
<add mimeType="application/json; charset=utf-8" enabled="true" />
<add mimeType="*/*" enabled="false" />
</dynamicTypes>
</httpCompression>
What am I missing? It looks like IIS not reads compression configurations from web.config at all.
After each change, I make application pool recycle, so it not a problem.
as per this ServerFault answer: https://serverfault.com/a/125156/117212 - you can't change httpCompression in web.config, it needs to be done in applicationHost.config file. Here is the code I use in my Azure web role to modify applicationHost.config file and add mime types for compression:
using (var serverManager = new ServerManager())
{
var config = serverManager.GetApplicationHostConfiguration();
var httpCompressionSection = config.GetSection("system.webServer/httpCompression");
var dynamicTypesCollection = httpCompressionSection.GetCollection("dynamicTypes");
Action<string> fnCheckAndAddIfMissing = mimeType =>
{
if (dynamicTypesCollection.Any(x =>
{
var v = x.GetAttributeValue("mimeType");
if (v != null && v.ToString() == mimeType)
{
return true;
}
return false;
}) == false)
{
ConfigurationElement addElement = dynamicTypesCollection.CreateElement("add");
addElement["mimeType"] = mimeType;
addElement["enabled"] = true;
dynamicTypesCollection.AddAt(0, addElement);
}
};
fnCheckAndAddIfMissing("application/json");
fnCheckAndAddIfMissing("application/json; charset=utf-8");
serverManager.CommitChanges();
}
ServerManager comes from Microsoft.Web.Administration package in NuGet.
You should check the whole config file hierarchy.
If you removed the section from applicationHost you may be inheriting from machine.config or a web.config of a parent directory.
I am building a service stack for the first time: hello world.
I have followed the step by step guide in here:
but it is giving me an error: Handler for Request not found: what could be the missing part? thanks.
here is my global.asax.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.SessionState;
using ServiceStack.ServiceHost;
using ServiceStack.WebHost.Endpoints;
namespace ServiceStack.SearchService
{
public class Global : System.Web.HttpApplication
{
public class Hello { public string Name { get; set; } }
public class HelloResponse { public string Result { get; set; } }
public class HelloService : IService<Hello>
{
public object Execute(Hello request)
{
return new HelloResponse { Result = "Hello, " + request.Name };
}
}
/// Web Service Singleton AppHost
public class HelloAppHost : AppHostBase
{
//Tell Service Stack the name of your application and where to find your web services
public HelloAppHost()
: base("Hello Web Services", typeof(HelloService).Assembly) { }
public override void Configure(Funq.Container container) { }
}
protected void Application_Start(object sender, EventArgs e)
{
//Initialize your application
var appHost = new HelloAppHost();
appHost.Init();
}
void Application_End(object sender, EventArgs e)
{
// Code that runs on application shutdown
}
void Application_Error(object sender, EventArgs e)
{
// Code that runs when an unhandled error occurs
}
void Session_Start(object sender, EventArgs e)
{
// Code that runs when a new session is started
}
void Session_End(object sender, EventArgs e)
{
// Code that runs when a session ends.
// Note: The Session_End event is raised only when the sessionstate mode
// is set to InProc in the Web.config file. If session mode is set to StateServer
// or SQLServer, the event is not raised.
}
}
}
here is my web.config:
<?xml version="1.0" encoding="utf-8"?>
<!--
For more information on how to configure your ASP.NET application, please visit
http://go.microsoft.com/fwlink/?LinkId=169433
-->
<configuration>
<connectionStrings>
<add name="ApplicationServices" connectionString="data source=.\SQLEXPRESS;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|\aspnetdb.mdf;User Instance=true" providerName="System.Data.SqlClient" />
</connectionStrings>
<system.web>
<compilation debug="true" targetFramework="4.0" />
<authentication mode="Forms">
<forms loginUrl="~/Account/Login.aspx" timeout="2880" />
</authentication>
<membership>
<providers>
<clear />
<add name="AspNetSqlMembershipProvider" type="System.Web.Security.SqlMembershipProvider" connectionStringName="ApplicationServices" enablePasswordRetrieval="false" enablePasswordReset="true" requiresQuestionAndAnswer="false" requiresUniqueEmail="false" maxInvalidPasswordAttempts="5" minRequiredPasswordLength="6" minRequiredNonalphanumericCharacters="0" passwordAttemptWindow="10" applicationName="/" />
</providers>
</membership>
<profile>
<providers>
<clear />
<add name="AspNetSqlProfileProvider" type="System.Web.Profile.SqlProfileProvider" connectionStringName="ApplicationServices" applicationName="/" />
</providers>
</profile>
<roleManager enabled="false">
<providers>
<clear />
<add name="AspNetSqlRoleProvider" type="System.Web.Security.SqlRoleProvider" connectionStringName="ApplicationServices" applicationName="/" />
<add name="AspNetWindowsTokenRoleProvider" type="System.Web.Security.WindowsTokenRoleProvider" applicationName="/" />
</providers>
</roleManager>
<httpHandlers>
<add path="*" type="ServiceStack.WebHost.Endpoints.ServiceStackHttpHandlerFactory, ServiceStack" verb="*" />
<add path="api*" type="ServiceStack.WebHost.Endpoints.ServiceStackHttpHandlerFactory, ServiceStack" verb="*" />
</httpHandlers>
</system.web>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true" />
<validation validateIntegratedModeConfiguration="false" />
<handlers>
<add path="*" name="ServiceStack.Factory" type="ServiceStack.WebHost.Endpoints.ServiceStackHttpHandlerFactory, ServiceStack" verb="*" preCondition="integratedMode" resourceType="Unspecified" allowPathInfo="true" />
</handlers>
</system.webServer>
<location path="servicestack">
<system.web>
<httpHandlers>
<add path="*" type="ServiceStack.WebHost.Endpoints.ServiceStackHttpHandlerFactory, ServiceStack" verb="*" />
<add path="servicestack*" type="ServiceStack.WebHost.Endpoints.ServiceStackHttpHandlerFactory, ServiceStack" verb="*"/>
</httpHandlers>
</system.web>
<!-- Required for IIS 7.0 -->
<system.webServer>
<modules runAllManagedModulesForAllRequests="true" />
<validation validateIntegratedModeConfiguration="false" />
<handlers>
<add path="*" name="ServiceStack.Factory" type="ServiceStack.WebHost.Endpoints.ServiceStackHttpHandlerFactory, ServiceStack" verb="*" preCondition="integratedMode" resourceType="Unspecified" allowPathInfo="true" />
</handlers>
</system.webServer>
</location>
</configuration>
I browse it by typing in the browser.
http://localhost:50097/ServiceStack.SearchService/servicestack/metadata
There is a small step missing from that list that you need if your going to map the services to a custom path. You can find it here:
To quote the missing step:
You also need to configure the root path in your AppHost.
public override void Configure(Container container)
{
SetConfig(new EndpointHostConfig { ServiceStackHandlerFactoryPath = "api" });
}
Where "api" is the name of the custom path you are using.
It looks like you're trying to host ServiceStack both at the / root path and at a mixture of /servicestack and /api custom paths. You need to pick one of them, not a combination of all 3. Here is the config if you want to host at the / root path:
<system.web>
<httpHandlers>
<add path="*" type="ServiceStack.WebHost.Endpoints.ServiceStackHttpHandlerFactory, ServiceStack" verb="*"/>
</httpHandlers>
</system.web>
<!-- Required for IIS 7.0 -->
<system.webServer>
<handlers>
<add path="*" name="ServiceStack.Factory" type="ServiceStack.WebHost.Endpoints.ServiceStackHttpHandlerFactory, ServiceStack" verb="*" preCondition="integratedMode" resourceType="Unspecified" allowPathInfo="true" />
</handlers>
</system.webServer>
The above should replace every other ServiceStack config mapping. Once you've done this you should be able to view the metadata page at:
http://localhost:50097/metadata
Note: If you're running ASP.NET on a port it is unlikely that you also have the Virtual Directory path /ServiceStack.SearchService/.
I had this exact issue I had and could not find a straight answer to - getting a 403.14 error on the simplest ServiceStack demo.
..:: Simple Answer ::..
Your answer is simple. You have confused your handlers by providing 3 instead of one as mentioned by Mythz. Also, You don't have a specified route for your request.
[Route("/hello")]
public class Hello { public string Name { get; set; } }
This will resolve both your 403.13 error (semantic issue) and you can go to your http://{localdomain}:{port}/hello and actually see the metadata (substitute the {port} with the actual port number IIS Express assigned to you). Without this adjustment, you'll need to go to http://{localdomain}:{port}/metadata.
..:: Detailed Answer ::..
Routing, as it relates to IIS in ServiceStack is done by semantics/convention. Since these routes are dynamic, when IIS is not provided proper routing at run time, it assumes that there is a folder issue (physical path) and throws the 403.14 error. At the same time, if you provide more than one path where there should be only one, bad things happen at run time when everything is wired up.
Just to be sure you have all the essentials, here are all the adjustments you need to make to the original code provided.
a. Adjust the web config file to handle just one path as explored in Mythz response
<system.web>
<httpHandlers>
<add path="*" type="ServiceStack.WebHost.Endpoints.ServiceStackHttpHandlerFactory, ServiceStack" verb="*"/>
</httpHandlers>
</system.web>
<!-- Required for IIS 7.0 -->
<system.webServer>
<handlers>
<add path="*" name="ServiceStack.Factory" type="ServiceStack.WebHost.Endpoints.ServiceStackHttpHandlerFactory, ServiceStack" verb="*" preCondition="integratedMode" resourceType="Unspecified" allowPathInfo="true" />
</handlers>
</system.webServer>
b. Make the route adjustment described earlier in this post.
I'm having difficulty making IIS 7 correctly compress a Json result from ASP.NET MVC. I've enabled static and dynamic compression in IIS. I can verify with Fiddler that normal text/html and similar records are compressed. Viewing the request, the accept-encoding gzip header is present. The response has the mimetype "application/json", but is not compressed.
I've identified that the issue appears to relate to the MimeType. When I include mimeType="*/*", I can see that the response is correctly gzipped. How can I get IIS to compress WITHOUT using a wildcard mimeType? I assume that this issue has something to do with the way that ASP.NET MVC generates content type headers.
The CPU usage is well below the dynamic throttling threshold. When I examine the trace logs from IIS, I can see that it fails to compress due to not finding a matching mime type.
<httpCompression directory="%SystemDrive%\inetpub\temp\IIS Temporary Compressed Files" noCompressionForProxies="false">
<scheme name="gzip" dll="%Windir%\system32\inetsrv\gzip.dll" />
<dynamicTypes>
<add mimeType="text/*" enabled="true" />
<add mimeType="message/*" enabled="true" />
<add mimeType="application/x-javascript" enabled="true" />
<add mimeType="application/json" enabled="true" />
</dynamicTypes>
<staticTypes>
<add mimeType="text/*" enabled="true" />
<add mimeType="message/*" enabled="true" />
<add mimeType="application/x-javascript" enabled="true" />
<add mimeType="application/atom+xml" enabled="true" />
<add mimeType="application/xaml+xml" enabled="true" />
<add mimeType="application/json" enabled="true" />
</staticTypes>
</httpCompression>
Make sure your %WinDir%\System32\inetsrv\config\applicationHost.config contains these:
<system.webServer>
<urlCompression doDynamicCompression="true" />
<httpCompression>
<dynamicTypes>
<add mimeType="application/json" enabled="true" />
<add mimeType="application/json; charset=utf-8" enabled="true" />
</dynamicTypes>
</httpCompression>
</system.webServer>
From the link of #AtanasKorchev.
As #simon_weaver said in the comments, you might be editing the wrong file with a 32 bit editor on a 64 bit Windows, use notepad.exe to make sure this file is indeed modified.
I have successfully used the approach highlighted here.
Use this guide
None of these answers worked for me. I did take note of the application/json; charset=utf-8 mime-type though.
I recommend this approach
Create CompressAttribute class, and set target action.
The ActionFilterAttribute approach updated for ASP.NET 4.x and Includes Brotli.NET package.
using System;
using System.IO.Compression;
using Brotli;
using System.Web;
using System.Web.Mvc;
public class CompressFilter : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
HttpRequestBase request = filterContext.HttpContext.Request;
string acceptEncoding = request.Headers["Accept-Encoding"];
if (string.IsNullOrEmpty(acceptEncoding)) return;
acceptEncoding = acceptEncoding.ToUpperInvariant();
HttpResponseBase response = filterContext.HttpContext.Response;
if (acceptEncoding.Contains("BR"))
{
response.AppendHeader("Content-encoding", "br");
response.Filter = new BrotliStream(response.Filter, CompressionMode.Compress);
}
else if (acceptEncoding.Contains("GZIP"))
{
response.AppendHeader("Content-encoding", "gzip");
response.Filter = new GZipStream(response.Filter, CompressionMode.Compress);
}
else if (acceptEncoding.Contains("DEFLATE"))
{
response.AppendHeader("Content-encoding", "deflate");
response.Filter = new DeflateStream(response.Filter, CompressionMode.Compress);
}
}
}