Fehlermeldung mit „DotNetOpenAuth.Core“ in ASP.NET MVC beseitigen

Eine neue Website mit ASP.NET MVC 4, frisch auf einen Server publiziert, lieferte die Fehlermeldung:

Die Datei oder Assembly „DotNetOpenAuth.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=2780ccd10d57b246“ oder eine Abhängigkeit davon wurde nicht gefunden. Die gefundene Manifestdefinition der Assembly stimmt nicht mit dem Assemblyverweis überein. (Ausnahme von HRESULT: 0x80131040)

Im Englischen klingt das ungefähr so:

Could not load file or assembly ‚DotNetOpenAuth.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=2780ccd10d57b246‘ or one of its dependencies. The located assembly’s manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)

Nach viel Suchen, fand ich schließlich die Lösung:

Da ich dieses „DotNetOpenAuth.Core“ via NuGet installiert hatte, wurde in meiner lokalen Web.config-Datei automatisch Einträge ergänzt. Diese Einträge haben im öffentlichen Web auf dem Webserver noch gefehlt.

Hier der komplette Ausschnitt:

<runtime>
 <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
 <dependentAssembly>
 <assemblyIdentity name="System.Web.Helpers" publicKeyToken="31bf3856ad364e35" />
 <bindingRedirect oldVersion="1.0.0.0-2.0.0.0" newVersion="2.0.0.0" />
 </dependentAssembly>
 <dependentAssembly>
 <assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" />
 <bindingRedirect oldVersion="0.0.0.0-4.0.0.0" newVersion="4.0.0.0" />
 </dependentAssembly>
 <dependentAssembly>
 <assemblyIdentity name="System.Web.WebPages" publicKeyToken="31bf3856ad364e35" />
 <bindingRedirect oldVersion="0.0.0.0-2.0.0.0" newVersion="2.0.0.0" />
 </dependentAssembly>
 <dependentAssembly>
 <assemblyIdentity name="WebGrease" publicKeyToken="31bf3856ad364e35" culture="neutral" />
 <bindingRedirect oldVersion="0.0.0.0-1.5.2.14234" newVersion="1.5.2.14234" />
 </dependentAssembly>
 <dependentAssembly>
 <assemblyIdentity name="DotNetOpenAuth.AspNet" publicKeyToken="2780ccd10d57b246" culture="neutral" />
 <bindingRedirect oldVersion="0.0.0.0-4.3.0.0" newVersion="4.3.0.0" />
 </dependentAssembly>
 <dependentAssembly>
 <assemblyIdentity name="DotNetOpenAuth.Core" publicKeyToken="2780ccd10d57b246" culture="neutral" />
 <bindingRedirect oldVersion="0.0.0.0-4.3.0.0" newVersion="4.3.0.0" />
 </dependentAssembly>
 <dependentAssembly>
 <assemblyIdentity name="Microsoft.Data.OData" publicKeyToken="31bf3856ad364e35" culture="neutral" />
 <bindingRedirect oldVersion="0.0.0.0-5.5.0.0" newVersion="5.5.0.0" />
 </dependentAssembly>
 <dependentAssembly>
 <assemblyIdentity name="Microsoft.Data.Edm" publicKeyToken="31bf3856ad364e35" culture="neutral" />
 <bindingRedirect oldVersion="0.0.0.0-5.5.0.0" newVersion="5.5.0.0" />
 </dependentAssembly>
 <dependentAssembly>
 <assemblyIdentity name="System.Spatial" publicKeyToken="31bf3856ad364e35" culture="neutral" />
 <bindingRedirect oldVersion="0.0.0.0-5.5.0.0" newVersion="5.5.0.0" />
 </dependentAssembly>
 <dependentAssembly>
 <assemblyIdentity name="System.Net.Http" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
 <bindingRedirect oldVersion="0.0.0.0-2.2.13.0" newVersion="2.2.13.0" />
 </dependentAssembly>
 </assemblyBinding>

Sobald ich das ergänzt hatte, war der Fehler weg.

Texte in JavaScript-Dateien in ASP.NET übersetzen

Der Artikel „Localize text in JavaScript files in ASP.NET“ hat eine hervorragende Lösung um Texte in JavaScript-Dateien (und auch in CSS-Dateien) zu übersetzen.

Das klappt sowohl mit ASP.NET-Website-Projekten, als auch mit ASP.NET-Web-Applikations-Projekten (also dem kompilierten).

Bis auf einen Fall, der mir heute passiert ist. Da kam immer eine Exception, dass er die Ressourcen für die aktuelle Culture nicht findet.

Die Lösung sah dann so aus, dass ich eine Funktion geändert habe.

Alt:

public static string TranslateScript(string text)
{
	if (string.IsNullOrEmpty(text))
	{
		return text;
	}
	else
	{
		var matches = Regex.Matches(text);
        var manager = new ResourceManager(typeof(Resources.Resources));

		foreach (Match match in matches)
		{
			var value = match.Groups[1].Value;

            var obj = manager.GetObject(value);
            if (obj != null)
			{
				text = text.Replace(match.Value, CleanText(obj.ToString()));
			}
		}

		return text;
	}
}

Neu:

public static string TranslateScript(string text)
{
	if (string.IsNullOrEmpty(text))
	{
		return text;
	}
	else
	{
		var matches = Regex.Matches(text);

		foreach (Match match in matches)
		{
			var value = match.Groups[1].Value;

			var obj = HttpContext.GetGlobalResourceObject(@"Resources", value);
            if (obj != null)
			{
				text = text.Replace(match.Value, CleanText(obj.ToString()));
			}
		}

		return text;
	}
}

D.h. ich habe den Zugriff über eine Klasse in einen Zugriff über „GetGlobalResourceObject“ umgewandelt, der erst zur Laufzeit versucht das aufzulösen.

Fehlermeldung „CS0103: Der Name ‚ViewBag‘ ist im aktuellen Kontext nicht vorhanden“ bei ASP.NET MVC 4 lösen

Heute habe ich bei einem neu deployten Projekt mit ASP.NET 4.5 und MVC 4 folgende Fehlermeldung erhalten:

CS0103: Der Name ‚ViewBag‘ ist im aktuellen Kontext nicht vorhanden
CS0103: The name ‚ViewBag‘ does not exist in the current context

Eine ähnliche Meldung lautet:

CS0103: Der Name ‚model‘ ist im aktuellen Kontext nicht vorhanden
CS0103: The name ‚model‘ does not exist in the current context

Lokal lief alles, auf dem Produktivserver kam die Fehlermeldung. Ich habe lange gesucht, bis ich die funktionierende Lösung gefunden habe.

Lösung

Die Lösung war im Endeffekt, dass es zwei Web.Config-Dateien gibt:

Diese im Views-Ordner hat bei mir gefehlt. Sobald ich diese hinzugefügt und entsprechend gefüllt hatte, hat alles funktioniert.

CryptographicException bei Verwendung von Oracle.ManagedDataAccess lösen

Gestern hatte ein Kollege beim Aufsetzen einer Website ASP.NET MVC 4 auf einem IIS unter Windows Server 2008 R2 eine Fehlermeldung:

[CryptographicException: Unbekannter Fehler -1073741766.]
   System.Security.Cryptography.ProtectedData.Protect(Byte[] userData, Byte[] optionalEntropy, DataProtectionScope scope) +504
   Oracle.ManagedDataAccess.Client.ConnectionString.Secure() +493
   OracleInternal.ConnectionPool.PoolManager`3.Initialize(ConnectionString cs) +1760
   OracleInternal.ConnectionPool.OraclePoolManager.Initialize(ConnectionString cs) +21
   OracleInternal.ConnectionPool.OracleConnectionDispenser`3.GetPM(ConnectionString cs, PM conPM, ConnectionString pmCS, Byte[] securedPassword, Byte[] securedProxyPassword, Boolean& bAuthenticated, Boolean& newPM) +296
   OracleInternal.ConnectionPool.OracleConnectionDispenser`3.Get(ConnectionString cs, PM conPM, ConnectionString pmCS, Byte[] securedPassword, Byte[] securedProxyPassword) +1576
   Oracle.ManagedDataAccess.Client.OracleConnection.Open() +3756
   OracleInternal.EntityFramework.EFOracleProviderServices.GetDbProviderManifestToken(DbConnection connection) +274
   System.Data.Common.DbProviderServices.GetProviderManifestToken(DbConnection connection) +91

[ProviderIncompatibleException: Der Anbieter hat keine ProviderManifestToken-Zeichenfolge zurückgegeben.]
   System.Data.Common.DbProviderServices.GetProviderManifestToken(DbConnection connection) +10947809
   System.Data.Entity.ModelConfiguration.Utilities.DbProviderServicesExtensions.GetProviderManifestTokenChecked(DbProviderServices providerServices, DbConnection connection) +48

[ProviderIncompatibleException: An error occurred while getting provider information from the database. This can be caused by Entity Framework using an incorrect connection string. Check the inner exceptions for details and ensure that the connection string is correct.]
   System.Data.Entity.ModelConfiguration.Utilities.DbProviderServicesExtensions.GetProviderManifestTokenChecked(DbProviderServices providerServices, DbConnection connection) +242
   System.Data.Entity.DbModelBuilder.Build(DbConnection providerConnection) +82
   System.Data.Entity.Internal.LazyInternalContext.CreateModel(LazyInternalContext internalContext) +88
   System.Data.Entity.Internal.RetryLazy`2.GetValue(TInput input) +248
   System.Data.Entity.Internal.LazyInternalContext.InitializeContext() +524
   System.Data.Entity.Internal.InternalContext.GetEntitySetAndBaseTypeForType(Type entityType) +26
   System.Data.Entity.Internal.Linq.InternalSet`1.Initialize() +71
   System.Data.Entity.Internal.Linq.InternalSet`1.GetEnumerator() +21
   System.Collections.Generic.List`1..ctor(IEnumerable`1 collection) +446
   System.Linq.Enumerable.ToList(IEnumerable`1 source) +80

Zunächst war es eine Herausforderung, statt den „normalen“ Oracle.DataAccess-Klassen die Oracle.ManagedDataAccess-Klassen zum Laufen zu bringen. Hier haben uns zwei Artikel geholfen:

Wir haben dann zum Lösen des eigentlichen Fehlers lange rumgesucht, viel ausprobiert und schließlich beim Weblog-Artikel „SOLVED: Windows Identity Foundation – “The system cannot find the file specified”“ fündig geworden.

Die Lösung bestand dann schlicht darin, im Anwendungspool (App Pool) für die Anwendung die Option „Benutzerprofil laden“ auf „True“ zu stellen:

IIS App Pool - Benutzerprofil laden

Danach lief alles wie gewünscht.

Fehlermeldung „Column does not belong to table“

Bei mir trat/tritt von Zeit-zu-Zeit die Fehlermeldung „Column does not belong to table“ auf, jeweils mit einer angegebenen Spalte, z.B.

Column ‚TestPlanID‘ does not belong to table

Oder

Column ‚ParentID‘ does not belong to table

Bzw. auf Deutsch

Spalte ‚RunnableTestCaseID‘ gehört nicht zu Tabelle

Da das nur teilweise auftritt und nur bei manchen Kunden und nur wenn viele SQL-Anfragen hintereinander ausgeführt werden, hat mir dieser Blogpost hier geholfen.

Der Autor dort geht davon aus, dass er ggf. Connections nicht rechtzeitig schließt. Als er das beseitigt hatte und der Fehler immer noch auftrat, hat er folgende Schlussfolgerungen/Aktionen daraus gezogen:

  1. Use „iisreset“ command every time you stop the IIS server.
  2. Walk through your code and make sure you are closing connection properly.
  3. Use „Connection Lifetime“ property of connection pool if required.
  4. Try to use ClearAllPools/ClearPool in appropriate application event.

Bei mir hat das teilweise geholfen, ggf. ist das ja doch irgend ein .NET-Bug, der irgendwann mal mit den neuesten Treibern für Microsoft SQL Server beseitigt sind.

Ergänzung 1:

Gerade heute bekomme ich wieder eine ähnliche Meldung bei einem Oracle-Projekt:

Column „FACH“ does not belong to table

Ich deute das so, dass das auch beim Oracle-Treiber so ein Issue ist. Es handelt sich hier um eine ASP.NET-4.0-Webanwendung. Andere sprechen auch darüber, dass es bei Ihnen auch bei Oracle auftritt. Vermutlich also ein Issue in ADO.NET. Einer schreibt:

We had this exact problem and we solved it.

Using static (C#) or shared (VB) .Net data classes on a multi-processor server will cause this error. The data class and its objects, e.g. DataTable, get resused across threads for some reason. So when when two requests come in at the same time, the second request overwrote the DataTable object variable with its own results, causing the first request to fail when it went looking for its tables, columns, etc.

This problem only occurred on multi-processor servers and went away when we declared our data classes without static or shared.

Wobei ich ihm das nicht ganz glaube. der Oracle provider hat auch eine Funktion ClearAllPools/ClearPool, diese werde ich jetzt mal aufrufen.

Ergänzung 2:

Den Fehler konnte ich jetzt beim Oracle erfolgreich beseitigen, indem ich meinen (eigenen) Cache deaktiviert habe. Eventuell hängt es mit dem Background-Cache-Aufräumen zusammen oder mit zu vielen Elementen im Cache.

Ergänzung 3 (2013-04-22):

Hatte jetzt erneut so einen Fall, den ich durch Cache-Deaktivieren lösen konnte.

Eventuell ist es ja sinnvoll, wenn eine DataTable aus dem Cache geholt wird, diese zu clonen, so dass nur die gleiche, nicht jedoch dieselbe DataTable genutzt wird und es so nicht zu Concurrency-Issues kommen kann. (Habe das jetzt probiert, hat in meinen Tests keine Änderung gebracht, leider).

Vorsicht bei „Debug.Assert“-Aufrufen in ASP.NET (2.0)-Webanwendungen!

Über vier Manntage hat mich insgesamt das folgende (in meinen Augen falsche) Verhalten von ASP.NET gekostet.

Beschreibung

  • Eine ASP.NET 2.0-Webanwendung läuft in der Testumgebung ganz normal und auch im Echtbetrieb.
  • Zu nicht-vorhersehbaren Zeiten „hängt“ die Anwendung auf einmal. D.h. die Anwendung reagiert für den Benutzer einfach nicht und der Browser lädt ewig.
  • Wenn ich dann den entsprechenden „w3wp.exe“ kille (ich habe extra einen AppPool nur für die eine Webanwendung gemacht), dann wird sofort automatisch ein neuer w3wp.exe gestartet und die Anwendung läuft wieder normal.

Ursache

Ein Aufruf von Debug.Assert in einer von der Webanwendung verwendeten DLL hat den Prozess zum Hängen gebracht.

  • Debug.Assert direkt in einer
    Webanwendung ausgeführt hält den „w3wp.exe“ nicht an, sondern wird
    schlicht ignoriert.
  • Debug.Assert indirekt
    in einer DLL, die von der Webanwendung verwendet wird, hält den
    w3wp.exe an und kann nur durch killen des „w3wp.exe“ beendet werden.

Lösung

Als schnellen Workaround habe ich jetzt alle Debug.Assert-Aufrufe in der DLL auskommentiert. Natürlich könnt Ihr auch schlicht alles im Release-Modus kompilieren, das ist aber in meinem Fall nicht nötig gewesen (keine Performance-Verbesserungen).

Fehlermeldung CS0013 beim Kompilieren einer ASP.NET 1.1-Anwendung mit Microsoft Visual Studio .NET 2003

Beschreibung

Beim Kompilieren einer ASP.NET 1.1-Anwendung mit Microsoft Visual Studio .NET 2003 auf einem Windows 2000 Server via Terminal Services („Remote Desktop“, RDP) trat folgende Fehlermeldung auf:

CS0013: Unerwarteter Fehler beim Schreiben der Metadaten in die Datei ‚C:\…\obj\Release\MyDll.dll‘ — ‚Unbekannter Fehler‘.

In Englisch sollte das in etwa so lauten:

CS0013: Unexpected error writing metadata to file ‚C:\…\obj\Release\MyDll.dll‘ — ‚Unknown error‘.

Die Fehlermeldung trat bei einem Projekt auf, das bereits über ein Jahr erfolgreich kompilierte. Nach einer kleinen Codeänderung kam auf einmal diese Fehlermeldung.

Ursache

Die erwähnte „kleine Codeänderung“ war, daß ich eine Klasse erstellt hatte, die von einer anderen Klasse abgeleitet hat, welche in einer dritten Klasse als Unterklasse enthalten war.

Also so was wie das hier:

public class A
{
    ...
    
    public class B
    {
        ....
    }

    ...
}

...

public class C : A.B
{
    ...
}

Scheinbar „verhaspelt“ sich der C#-Compiler da irgendwo. In anderen Fällen hat das selbe Prinzip auch schon oft funktioniert. Nur in diesem Fall hier aus irgendeinem Grund nicht.

Lösung

Nachdem ich die Klasse B „global“ gemacht hatte, kompilierte alles wieder:

public class A
{
    ... 
}

...

public class B
{
    ....
}

...

public class C : B
{
    ...
}