Debugging the ASP.NET Web Resource request errors is difficult because the error does not give you the name of the exact missing web resource. it says some thing like :
"Message: This is an invalid webresource request."
This does not give you anything.
One thing that we can try is to use Fiddler to figure out which request is causing this to happen.
This gives you a very important input to debug further.
If it gives something like this "http://<websiteName>/WebResource.axd?d=<digest>
Then this post fits the problem context.
What this means is we are dealing with a forgotten [WebResource] attribute that has no matching resource in your assembly
We can decrypt the query string data that was being passed to WebResource.axd and extract the resource and assembly name from it. MSDN documentation tells you that meaning of the query string parameters "D" and "t". Basically "d" - has the encoded URL and "t" has the timestamp.
The encryption uses MachineKeySection.EncryptOrDecryptData() method, so we can easily decrypt that. Unfortunately, the method is declared internal. Here goes the code:
The encryption uses MachineKeySection.EncryptOrDecryptData() method, so we can easily decrypt that. Unfortunately, the method is declared internal. Here goes the code:
byte[] encryptedData = HttpServerUtility.UrlTokenDecode(urlEncodedData);
Type machineKeySection = typeof(MachineKeySection);
Type[] paramTypes = new Type[] { typeof(bool), typeof(byte[]), typeof(byte[]), typeof(int), typeof(int) };
MethodInfo encryptOrDecryptData = machineKeySection.GetMethod("EncryptOrDecryptData", BindingFlags.Static | BindingFlags.NonPublic, null, paramTypes, null);
try
{
byte[] decryptedData = (byte[])encryptOrDecryptData.Invoke(null, new object[] { false, encryptedData, null, 0, encryptedData.Length });
string decrypted = Encoding.UTF8.GetString(decryptedData);
decryptedLabel.BackColor = Color.Lime;
decryptedLabel.Text = decrypted;
}
catch (TargetInvocationException)
{
decryptedLabel.BackColor = Color.Red;
decryptedLabel.Text = "Error decrypting data. Are you running your page on the same server and inside the same application as the web resource URL that was generated?";
}
Type machineKeySection = typeof(MachineKeySection);
Type[] paramTypes = new Type[] { typeof(bool), typeof(byte[]), typeof(byte[]), typeof(int), typeof(int) };
MethodInfo encryptOrDecryptData = machineKeySection.GetMethod("EncryptOrDecryptData", BindingFlags.Static | BindingFlags.NonPublic, null, paramTypes, null);
try
{
byte[] decryptedData = (byte[])encryptOrDecryptData.Invoke(null, new object[] { false, encryptedData, null, 0, encryptedData.Length });
string decrypted = Encoding.UTF8.GetString(decryptedData);
decryptedLabel.BackColor = Color.Lime;
decryptedLabel.Text = decrypted;
}
catch (TargetInvocationException)
{
decryptedLabel.BackColor = Color.Red;
decryptedLabel.Text = "Error decrypting data. Are you running your page on the same server and inside the same application as the web resource URL that was generated?";
}
The tricky part is that we use the MachineKeySection class to do our job and we deal with encryption settings specific to the current application. This means that decrypting web resource URL will work if and only if you run the code on the same server and from the same web application that generated the resource.
I am attaching a standalone page that you can drop in your application’s root and request it. You can then paste a web resource URL in the text box and decrypt it. You can even drop controls on the page and the dropdown will be automatically filled with all registered scripts and stylesheets served from web resources.
No comments:
Post a Comment