by Njål

The directory specified for caching compressed content is invalid. Static compression is being disabled.

image

 

After adding this in my web.config (Azure Project)…

<staticContent>
    <mimeMap fileExtension=".svg" mimeType="image/svg+xml" />
</staticContent>

…IIS refused to serve any static content – such as js and png files. Log entries in Event Viewer said:

The directory specified for caching compressed content
C:UsersxxxAppDataLocaldftmpResourcesb503ce54-3fba-4772-beaa-415d94ffc214temptempRoleTempiisexpressIIS Temporary Compressed Files9ef2ab2d-28fc-4554-a09c-5ba867eb1d19 is invalid.
Static compression is being disabled.

The problem was that .svg files were already added to the staticContent list in my applicationHost.config – but still – the error message shown in the Event Viewer is pretty useless. There is nothing wrong with the directory specified to store compressed content.

So if you suddenly get this error – undo any changes in Web.config (remove all config under staticContent) and restart IIS (Express).

by Joakim

Automatic Config Transformations

My fellow blogger here on the Degree Blog, Thor Halvor, had a blog post not too long ago titled “Don’t let the Configuration transform your Configs” where he recommends that people don’t transform their config files based on the solution configuration, and he points out a lot of things which is important to keep in mind. I, however, think that using the solution configurations to control which transformation files are applied to your config files works quite well.

As Thor Halvor points out in his blog post, you get a few extra config files when you create a web application in Visual Studio, namely Web.Debug.config, and Web.Release.config. These files are the XML transform files for Web.config, and when you build you application locally, they do exactly nothing (no matter if you have selected the debug or release solution configuration). If you use the “Build Deployment Package” or the “Publish” functionality in Visual Studio however, they are applied to your web.config file based on the currently selected solution configuration. Now this might work fine for a small personal project like your own homepage etc., but I doubt many people use this on large work projects. Another problem with this functionality (as Thor Halvor points out), is that it only works for Web.config, and in larger projects you often have more than one config-file (connection strings in a separate file, etc.).

So how can we use xml transform files for more than Web.config, and have the transformation be performed as part of an automated build on a build server? By adding a new target to the Web Application’s project file (.csproj) which will run as a part of the build (You need to right click on the project and choose “Edit project file”).

<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  .
  .
  .
  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
       Other similar extension points exist, see Microsoft.Common.targets.
  <Target Name="BeforeBuild">
  </Target>
  <Target Name="AfterBuild">
  </Target> -->
  <Target Name="TransformConfigFiles" AfterTargets="AfterBuild" Condition="'$(TransformConfigFiles)'=='true'">
    <ItemGroup>
      <DeleteAfterBuild Include="$(WebProjectOutputDir)Web.*.config" />
      <DeleteAfterBuild Include="$(WebProjectOutputDir)ConnectionStrings.*.config" />
    </ItemGroup>
    <TransformXml Source="Web.config" Transform="$(ProjectConfigTransformFileName)" Destination="$(WebProjectOutputDir)Web.config" />
    <TransformXml Source="ConnectionStrings.config" Transform="ConnectionStrings.$(Configuration).config" Destination="$(WebProjectOutputDir)ConnectionStrings.config" />
    <Delete Files="@(DeleteAfterBuild)" />
  </Target>
  .
  .
  .
</Project>

This new target will run after the “AfterBuild”-target, and it will transform both Web.config and ConnectionStrings.config, given that you specify the property “TransformConfigFiles” to be “true” (because we don’t want this be be done when we’re developing the application and building it in Visual Studio. As you can see above it uses the “Configuration”-property to decide which xml transform file to use (this property will contain the name of the selected solution configuration). After performing the transformation, it will clean-up/delete the xml transform files.

ConfigTransform1As you can see, I have created an additional config file, namely ConnectionStrings.config, as well as xml transform files for it (ConnectionStrings.Debug.config and ConnectionStrings.Release.config). The transformation files I’ve created aren’t group under the actual config file like Web.config’’s xml transformation files are, but if you wanted to you could edit the project file to do this.

You need to have xml transformation files for each solution configuration for those config files you want to transform, and they must all be named as <ConfigFileName>.<SolutionConfigurationName.config. I.e. if you create a new solution configuration called “Production” you would need to create a xml transform file called ConnectionString.Production.config (for Web.config you would just need to right click on it and select “Add Config Transforms”.

 

 

 

Inside my transformation files I’ve just put some simple transformations that will allow me to see that the config files are actually being transformed.

Web.config:
<configuration>
  <connectionStrings configSource="ConnectionStrings.config" />
  <appSettings>
    <add key="Configuration" value="" />
    ...
  </appSettings>
  ...
</configuration>

Web.Release.config:
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
  <appSettings>
    <add key="Configuration" value="Release" xdt:Transform="Replace" xdt:Locator="Match(key)" />
  </appSettings>
  </system.web>
</configuration>

ConnectionStrings.config:
<connectionStrings>
  <add name="DefaultConnection" connectionString="Data Source=(local);Initial Catalog=dbMVC4;Integrated Security=True" providerName="System.Data.SqlClient" />
</connectionStrings>

ConnectionStrings.Release.config:
<connectionStrings xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
  <add name="DefaultConnection" connectionString="Data Source=PreProdDatabaseServer;Initial Catalog=dbMVC4;Integrated Security=True" providerName="System.Data.SqlClient" xdt:Transform="Replace" xdt:Locator="Match(name)" />
</connectionStrings>

In order to build the Web Application and have the config transformations take place we must run msbuild and specify the solution configuration we want to use, and that TransformConfigFiles should be true.

Running msbuild manually from the Visual Studio command prompt:

msbuild "C:...Testing.sln" /p:Configuration=Release /p:TransformConfigFiles=true /p:OutDir=C:TempTesting_Release

Under “C:TempTesting_Release_PublishedWebsitesMVC4” one should be able to find the Web Application with transformed config-files.

Now for the cool part, this approach will also work on your TFS build server, in your build definition just specify the build configuration and add TransformConfigFiles=true to the MSBuild Arguments.

ConfigTransformTFS

On the project I’m currently working on, we have successfully been using this solution with TFS 2010 to automatically build and deploy our web application to the different testing environments for the better part of a year now! Smile

by Njål

Alvorlig sikkerhetshull i Asp.net

Microsoft annonserte for under en uke siden at det er oppdaget et relativt alvorlig sikkerhetshull i Asp.net / IIS som gjør at private filer som f.eks. web.config kan lastes ned. I disse filene ligger det ofte sensitiv informasjon som brukernavn / passord til databaser osv – så dette kan potensielt få store konsekvenser.

Inntil Microsoft lanserer en patch via Windows Update, anbefales det å slå på CustomErrors i Web.Config – som forhindrer angriperen i å bryte seg inn.

Se Scott Guthries blogg for detaljer:
http://weblogs.asp.net/scottgu/archive/2010/09/18/important-asp-net-security-vulnerability.aspx

by Andreas

Log4Net i Sharepoint 2010 web parts

All kode (av noenlunde kvalitet…) som kjører i et produksjonsmiljø logger. Eller burde gjøre det. Om det er til fil, database, eventlogg eller remote over eteren har ikke noe å si – et sted bør det holdes varig track på hva som skjer i en applikasjon. Da jeg hev meg på utvikling i Sharepoint var en av de første “utfordringene” hvordan jeg skulle få skrevet til egne loggfiler i stedet for å bruke de interne Sharepointloggene. Hvorfor? Vel.. det skjer mye Sharepoint. Mye som du sannsynligvis ikke er interessert i, og som ikke nødvendigvis er relevant for den feilen du leter etter grunnen til.

Log4Net er en .NET-portering av Log4J. Den gjør det enkelt for en applikasjon å logge til fil. Det er omtrent det jeg tar med av bakgrunn, siden den som leser dette innlegget sannsynligvis har brukt det før og bare vil se hvordan det brukes i Sharepoint. Jeg tar heller ikke med mulighetene for å bruke Log4Net til å sende mail via SMTP, men den er verdt å få med seg at eksisterer.

Sharepoint er bygd på ASP.NET, og du kan derfor bruke samme fremgangsmåte som du hadde gjort i en hvilken som helst annen ASP.NET-applikasjon. Det som utgjør forskjellen er at en web part ikke nødvendigvis har en web.config-fil. I dette eksemplet bruker jeg den som ligger i roten på selve Sharepoint-instansen (På site collection-nivå). Det er ikke noe i veien for å bruke en mer lokal web.config, men det utgjør ikke noe vesentlig forskjell i demosammenheng.

1. Legg til en referanse til log4net.dll
Denne må enten registreres i GAC manuelt, eller så kan du legge den til Package-elementet i web part-prosjektet. Sjekk dette innlegget for en gjennomgang av det.

2. Legg inn den vanlige ConfigSection og konfigurasjon i web.config
I denne demoen bruker jeg web.config for en hel site collection (ligger gjerne her C:inetpubwwwrootwssVirtualDirectories80web.config).

Øverst i web.config legger jeg log4net-noden som første element under “configSections”:




....

Deretter legger jeg appender-config som et element rett før “system.web”:






















.......

3. Legg til en entry i AssemblyInfo.cs
Her settes ConfiguratorAttribute til å peke på web.config som konfigurasjonsfil:


[assembly: log4net.Config.XmlConfiguratorAttribute(ConfigFile = "web.config", Watch = true)]

4. Legg til en statisk instans av loggeren på klassenivå slik som før (denne henter generisk ut klassens navn i stedet for å selv måtte sette dette for hver klasse):


private static readonly log4net.ILog _log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

5. Logging burde nå (med Guds velvilje og litt triksing med skriverettighetene i målmappen) fungere:


_log.Info("Degree Blogg sparte meg akkurat for masse jobb!");
_log.Warn(" (and I'm a poet and didn't know it) ");

by Njål

Laste opp store filer i IIS 7.0

For å laste opp store filer (eller f.eks. sende store bytearray’er via Web Services) inn til en Microsoft IIS server kreves det en liten tweak.

I IIS 6.0 holdt det å justere opp maxRequestLength parametren i web.config. I IIS 7.0 må man også legge til/endre under <system.webServer>. Eksempelet under tillater å laste opp filer som er 2 GB store (IIS 7.0 støtter ikke større mengder såvidt jeg vet).