Running Classic ASP on IIS 7.5 in STA - iis

Trying to for a Classic ASP webapp on IIS 7.5 to run in STA mode by enabling AspCompat. This is a hard requirement due to a COM Object being instantiated that is not thread safe.
<%# Page Language="VBScript" AspCompat="true" Debug="false" %>
Although the settings is forced through AspCompat, the behaviour when rendering websites seems not to be consequent.
The expected behaviour:
On every page request, the ComServer.exe starts, does some work and closes.
When another request arrives, processing waits for the first request to finish.
I know this is bad performance whise. However sadly, this is a hard requirement for running the legacy ComServer.
This behaviour is visible when there are multiple parallel requests comming from the same client. When multiple requests come from different clients however, the behaviour changes:
After every batch of requests, the ComServer is closed.
If there is only one request, the ComServer is stopped after the request
If there are multiple requests, they are all processed under the same ComServer
Action 3 causes the ComServer to sometimes fail, causing COMExceptions.
Although the issue is probably caused by bad design of the COMObject, I cannot change this. The only thing I can do is surrounding COMObject access with an Application Lock
Dim oComSvr as object
oComSvr=Server.CreateObject("com_svr.my_svr")
...
Application.Lock
returnValue=oComSvr.selectform(value1, value2, ...)
Application.Unlock
However this prevents most COMExceptions, there are still specific timings that result in a COMException.
What can I do to force constant STA behaviour, also if multiple requests to the same IIS server come from different clients.
Tried to follow this article and implemented Page_Load to prevent the object being created before STA mode. http://technet.microsoft.com/en-ca/zwk9h2kb(v=vs.95).aspx
It still looks like if AspCompat is being ignored.
[COMException (0x800706be): Creating an instance of the COM component with CLSID {B28A581A-6CE3-46E9-871F-B2E129F7D238} from the IClassFactory failed due to the following error: 800706be.]
System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandle& ctor, Boolean& bNeedSecurityCheck) +0
System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean fillCache) +86
System.RuntimeType.CreateInstanceImpl(Boolean publicOnly, Boolean skipVisibilityChecks, Boolean fillCache) +230
System.Activator.CreateInstance(Type type, Boolean nonPublic) +67
System.Activator.CreateInstance(Type type) +6
System.Web.HttpServerUtility.CreateObject(String progID) +122
ASP.myapp.Page_Load() +1670
System.Web.Util.CalliHelper.ArglessFunctionCaller(IntPtr fp, Object o) +8
System.Web.Util.CalliEventHandlerDelegateProxy.Callback(Object sender, EventArgs e) +8760147
System.Web.UI.Control.OnLoad(EventArgs e) +99
System.Web.UI.Control.LoadRecursive() +50
System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +627
Update:
Read here and here that it is important WHERE the STA object is instantiated. Instantiating the object during construction time will cause this issue.
http://technet.microsoft.com/en-ca/zwk9h2kb(v=vs.95).aspx
http://msdn.microsoft.com/en-us/library/5dws599a(vs.71).aspx
Tried instantiating in Page_Load as in the example. However this does not change the behaviour when accessing the page from another client.

OK we've had this and this is how I've found a solution.. In our case I think it was linked to parent paths but could have been session state too...
Browse to C:\Documents and Settings\$your user name$\My Documents\IIS 7.5\config
Open applicationHost.config
Find the section
Change the section to the following… By default it only had the cache and empty limits bits but feel free to adjust any parameters you don't want.
<asp
enableParentPaths="true"
bufferingOn="true"
errorsToNTLog="true"
appAllowDebugging="true"
appAllowClientDebug="true"
scriptErrorSentToBrowser="true">
<session allowSessionState="true" />
<cache diskTemplateCacheDirectory="%TEMP%\iisexpress\ASP Compiled Templates" />
<limits />
</asp>
Save and restart iis 7.5.

if it is surrounding COMObject access with an Application Lock
However, if you write something like this in a sample format to get an idea.
Application["Counter"] = (int) Application["Counter"] + 1;
then you will need to use Lock and Unlock as follows:
Application.Lock();
Application["Counter"] = (int) Application["Counter"] + 1;
Application.Unlock();
This is because the thread might be interrupted between the read from, and then write to, the Application object, and another thread could therefore alter the value stored for the "Counter".

Related

Opening Office Application Error: Microsoft.Office.Interop.Excel / Microsoft.Office.Interop.Word

I am hoping that someone can give a little insight and/or instance.
I am experiencing an error trying to create an instance of an Excel or Word application. The application I am working on is using interop assemblies to manipulate Excel and Word. In both cases, I have been successful in doing so in the past, the problems/errors began only recently. I've noticed multiple posts about similar error messages and have looked through them, but none addressed a similar issue or provided relevant insights.
In attempting to create an instance of Excel, the resulting error is similar to the following:
{System.Runtime.InteropServices.COMException (0x80080005): Retrieving
the COM class factory for component with CLSID
{00024500-0000-0000-C000-000000000046} failed due to the following
error: 80080005 Server execution failed (Exception from HRESULT:
0x80080005 (CO_E_SERVER_EXEC_FAILURE)). at
System.Runtime.Remoting.RemotingServices.AllocateUninitializedObject(RuntimeType
objectType) at
System.Runtime.Remoting.Activation.ActivationServices.CreateInstance(RuntimeType
serverType) at
System.Runtime.Remoting.Activation.ActivationServices.IsCurrentContextOK(RuntimeType
serverType, Object[] props, Boolean bNewObj) at
System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean
publicOnly, Boolean noCheck, Boolean& canBeCached,
RuntimeMethodHandleInternal& ctor, Boolean& bNeedSecurityCheck) at
System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean
skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark) at
System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly,
Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark)
at System.Activator.CreateInstance(Type type, Boolean nonPublic) at
System.Activator.CreateInstance(Type type)
I am encountering a similar error when trying to create an instance of Word. Again, my code has been doing this with no problem, until recently.
I'm thinking this may have started with possibly with recent upgrades to the Office instance on my development machine.
The references for both Interop assemblies (Microsoft.Office.Interop.Excel and Microsoft.Office.Interop.Word) associated with my project have Embed Interop Types set to TRUE)
If I am interpreting the error text correctly, the code is looking for the typelib/class id (i.e., {00024500-0000-0000-C000-000000000046}) to be in the current machine's registry and cannot find it. I did search the \HKEY_CLASSES_ROOT\TypeLib folder in the registry and did not see it. My question would be, why is it looking for that particular id? Of course, I may be completely out in left field on this line of reasoning.
Since I am seeing similar effects in both contexts, I have to believe that the issue's cause here is on the Office level, rather than either application. To the best of my knowledge, no change was made to the code or the Interop assembly references in the project.
Any insights and/or suggestions would, of course, be greatly appreciated.
I am using VS 2017 (64-bit) on Windows 10.

CryptographicException KeySet does not exists

I am using Thinktecture Identity server and running it in azure. The issue I am having is that sometimes when I read the Federation metadata XML file or while signing in I get this Keyset does not exists CryptoGraphic exception . Now i know these exceptions can be caused if we do not have proper permissions but the thing is that it just happens sometimes and other times it is working fine. I am not sure how to debug this. Can someone please lead me in some direction.
Also if someone has any idea about what kind of certificate is this system assembly trying to read and how it is configured that will be very helpful as well.
at System.Security.Cryptography.Utils.CreateProvHandle(CspParameters parameters, Boolean randomKeyContainer)
at System.Security.Cryptography.Utils.GetKeyPairHelper(CspAlgorithmType keyType, CspParameters parameters, Boolean randomKeyContainer, Int32 dwKeySize, SafeProvHandle& safeProvHandle, SafeKeyHandle& safeKeyHandle)
at System.Security.Cryptography.RSACryptoServiceProvider.GetKeyPair()
at System.Security.Cryptography.RSACryptoServiceProvider..ctor(Int32 dwKeySize, CspParameters parameters, Boolean useDefaultKeySize)
at System.Security.Cryptography.X509Certificates.X509Certificate2.get_PrivateKey()
at System.IdentityModel.Tokens.X509AsymmetricSecurityKey.get_PrivateKey()
at System.IdentityModel.Tokens.X509AsymmetricSecurityKey.GetSignatureFormatter(String algorithm)
at System.IdentityModel.SignedXml.ComputeSignature(SecurityKey signingKey)
at System.IdentityModel.EnvelopedSignatureWriter.ComputeSignature()
at System.IdentityModel.EnvelopedSignatureWriter.OnEndRootElement()
at System.IdentityModel.EnvelopedSignatureWriter.WriteEndElement()
at System.IdentityModel.Metadata.MetadataSerializer.WriteEntityDescriptor(XmlWriter inputWriter, EntityDescriptor entityDescriptor)
at System.IdentityModel.Metadata.MetadataSerializer.WriteMetadataCore(XmlWriter writer, MetadataBase metadataBase)
at System.IdentityModel.Metadata.MetadataSerializer.WriteMetadata(XmlWriter writer, MetadataBase metadata)
at PeachCourt.Auth.API.Protocols.FederationMetadata.WSFederationMetadataGenerator.Generate()
at Test.Auth.API.Protocols.FederationMetadata.FederationMetadataController.<Generate>b__1()
at Test.Auth.API.Helper.Cache.ReturnFromCache[T](ICacheRepository cacheRepository, String name, Int32 ttl, Func`1 action)
at Test.Auth.API.Protocols.FederationMetadata.FederationMetadataController.Generate()
It is trying to read the certificate that you have configured for token signing. The error message typically indicated that the worker process account has no read access to the private key.

Windows azure redis cache migration issue

We are hosting our site on windows azure where site is running on multiple instances.Due to multiple instances we were using shared cache for storing session values. As Microsoft is going to stop shared cache and recommended to use redis cache to store session. I modified project to use redis cache and it worked for most of the pages. My problem is that, we have a very important page "search page" (we are using lucene.net for search functionality) in our site which stores a lot of data in session and this page is not working. After hitting search button, it shows connecting status in address bar for a long time and goes to oops page of website. We are recording error messages in DB so after looking at there we found following error message.
System.Runtime.Serialization.SerializationException: Type 'myWeb.clsSearchCriteria+ContentCriteria' in Assembly 'HelmBriscoeWeb, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' is not marked as serializable.
at System.Runtime.Serialization.FormatterServices.InternalGetSerializableMembers(RuntimeType type)
at System.Runtime.Serialization.FormatterServices.GetSerializableMembers(Type type, StreamingContext context)
at System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.InitMemberInfo()
at System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.InitSerialize(Object obj, ISurrogateSelector surrogateSelector, StreamingContext context, SerObjectInfoInit serObjectInfoInit, IFormatterConverter converter, ObjectWriter objectWriter, SerializationBinder binder)
at System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.Serialize(Object obj, ISurrogateSelector surrogateSelector, StreamingContext context, SerObjectInfoInit serObjectInfoInit, IFormatterConverter converter, ObjectWriter objectWriter, SerializationBinder binder)
at System.Runtime.Serialization.Formatters.Binary.ObjectWriter.Serialize(Object graph, Header[] inHeaders, __BinaryWriter serWriter, Boolean fCheck)
at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize(Stream serializationStream, Object graph, Header[] headers, Boolean fCheck)
at Microsoft.Web.Redis.RedisUtility.GetBytesFromObject(Object data)
at Microsoft.Web.Redis.RedisUtility.AppendUpdatedOrNewItemsInList(ChangeTrackingSessionStateItemCollection sessionItems, List`1 list)
at Microsoft.Web.Redis.RedisConnectionWrapper.TryUpdateIfLockIdMatchPrepare(Object lockId, ISessionStateItemCollection data, Int32 sessionTimeout, String[]& keyArgs, Object[]& valueArgs)
at Microsoft.Web.Redis.RedisConnectionWrapper.TryUpdateIfLockIdMatch(Object lockId, ISessionStateItemCollection data, Int32 sessionTimeout)
at Microsoft.Web.Redis.RedisSessionStateProvider.SetAndReleaseItemExclusive(HttpContext context, String id, SessionStateStoreData item, Object lockId, Boolean newItem)
at System.Web.SessionState.SessionStateModule.OnReleaseState(Object source, EventArgs eventArgs)
at System.Web.SessionState.SessionStateModule.OnEndRequest(Object source, EventArgs eventArgs)
at System.Web.HttpApplication.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)
I am not sure if this is related to my problem but seems if this is fixed, page will work properly. Has anyone any idea why this error occurred and how can I fix it?
Thanks
I solved this problem myself by adding serialization attribute to class like below.
<Serializable()> _
Public Class clsSearchCriteria
Thanks

Value does not fall within the expected range. at Microsoft.SharePoint.SPWeb.GetWebRelativeUrlFromUrl while checking out file from doc library

I have an extrnet site that has a shared document file. I can upload
files just fine, view them, etc... But when I try to check one out to
make changes, I immetiately get this:
Value does not fall within the expected range. at
Microsoft.SharePoint.SPWeb.GetWebRelativeUrlFromUrl(String strUrl,
Boolean includeQueryString, Boolean canonicalizeUrl)
at Microsoft.SharePoint.SPWeb.GetWebRelativeUrlFromUrl(String
strUrl)
at Microsoft.SharePoint.SPWeb.GetFile(String strUrl)
at Microsoft.SharePoint.ApplicationPages.Checkin.get_File()
at Microsoft.SharePoint.ApplicationPages.Checkin.OnLoad(EventArgs e)
at System.Web.UI.Control.LoadRecursive()
at System.Web.UI.Page.ProcessRequestMain(Boolean
includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
And this is logged on as the administrator. Any ideas would be
greately appreciated.
I have previously received this error when trying to access a system running on a 64 bit OS when the code is 32bit OR the custom .NET code is running on a version of .NET higher than 3.5.
I am not completely sure which, otherwise it is just as the error says and that the url being passed into the GetWebRelativeUrlFromUrl does not match any SPSites in the farm.
it was occurred for me on Web.GetFile method. and it was resolved after finding that this function only works if the file is in the current site and not the root site in my case. after copying the file in the site assets of working site and changing the file path it works
using (Stream tplStream =
SPContext.Current.Web.GetFile("/sitename/SiteAssets/file.docx").OpenBinaryStream())

Why would a web part fail on constructor the first time it's being added to a page?

This question is a bit specific (MOSS2007) and I don't high hopes for getting an answer, but maybe luck will smile upon me.
I have a web part that works except the very first time it's being added to a page. It throws an exception inside a constructor when I'm trying to open a connection to a SQL server. The demand for the SqlClientPermission permission fails. When I say it works, I mean it is properly registered in any regard and works in every other case, including subsequent calls.
Someone said there is no way out. I'd like to know why. Is it by design?
I went so far as to give a full trust to everything I could (changed every .config file I could find on my server), but it did not help.
It appears that SharePoint is doing some kind of remoting the first time it adds a web part, which appears to run with minimal trust the first time it's constructed (same as defined in web_minimaltrust.config for ASP.Net). Attempts to grant permissions for everything in everything did not yield any fruitful results.
My solution was to move the data access code to the OnInit method, but that is irritating. Does anyone have any insight?
Thank you.
Some extra info from the debugger.
The only permitted permissions were:
<PermissionSet class="System.Security.PermissionSet" version="1">
<IPermission class="System.Security.Permissions.SecurityPermission, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Flags="Execution"/>
<IPermission class="System.Web.AspNetHostingPermission, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Level="Minimal"/>
</PermissionSet>
The inner exception stack:
hresult = -2146233078
mscorlib
at System.Security.CodeAccessSecurityEngine.Check(Object demand, StackCrawlMark& stackMark, Boolean isPermSet)
at System.Security.PermissionSet.Demand()
at System.Data.Common.DbConnectionOptions.DemandPermission()
at System.Data.SqlClient.SqlConnection.PermissionDemand()
at System.Data.SqlClient.SqlConnectionFactory.PermissionDemand(DbConnection outerConnection)
at System.Data.ProviderBase.DbConnectionClosed.OpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory)
at System.Data.SqlClient.SqlConnection.Open()
at System.Data.Linq.SqlClient.SqlConnectionManager.UseConnection(IConnectionUser user)
at System.Data.Linq.SqlClient.SqlProvider.get_IsSqlCe()
at System.Data.Linq.SqlClient.SqlProvider.InitializeProviderMode()
at System.Data.Linq.SqlClient.SqlProvider.System.Data.Linq.Provider.IProvider.Execute(Expression query)
at System.Data.Linq.DataQuery`1.System.Linq.IQueryProvider.Execute[S](Expression expression)
at System.Linq.Queryable.Count[TSource](IQueryable`1 source)
at IManageDocumentsPart.ClientSideDocumentsWebPart.GetOfficeCode(Int32 employeeId)
at IManageDocumentsPart.ClientSideDocumentsWebPart..ctor()
The full stack:
IManageDocumentsPart.DLL!IManageDocumentsPart.ClientSideDocumentsWebPart.ClientSideDocumentsWebPart() Line 98 C#
[Native to Managed Transition]
[Managed to Native Transition]
mscorlib.dll!System.RuntimeType.CreateInstanceSlow(bool publicOnly, bool fillCache = true) + 0x68 bytes
mscorlib.dll!System.Activator.CreateInstance(System.Type type, bool nonPublic) + 0x43 bytes
System.Web.dll!System.Web.HttpRuntime.FastCreatePublicInstance(System.Type type) + 0x56 bytes
System.Web.dll!System.Web.UI.WebControls.WebParts.WebPartManagerInternals.CreateObjectFromType(System.Type type) + 0x7 bytes
System.Web.dll!System.Web.UI.WebControls.WebParts.WebPartManager.ImportWebPart(System.Xml.XmlReader reader = {EndElement, Name="metaData"}, out string errorMessage = null) + 0x35d bytes
Microsoft.SharePoint.dll!Microsoft.SharePoint.WebPartPages.SPWebPartManager.ImportWebPartBase(System.Xml.XmlReader reader = {EndElement, Name="metaData"}, string importErrorMessage = "Cannot import this Web Part.", out string errorMessage = null) + 0x25 bytes
Microsoft.SharePoint.dll!Microsoft.SharePoint.WebPartPages.WebPartImporter.CreateWebPart(bool clearConnections = true) + 0x1b4 bytes
Microsoft.SharePoint.dll!Microsoft.SharePoint.WebPartPages.WebPartImporter.Import(Microsoft.SharePoint.WebPartPages.SPWebPartManager manager = {Microsoft.SharePoint.WebPartPages.SPWebPartManager}, System.Xml.XmlReader reader = {None}, bool clearConnections = true, System.Uri webPartPageUri = {http://v-sp2007/testsite/default.aspx?PageView=Shared}, Microsoft.SharePoint.SPWeb spWeb = {Microsoft.SharePoint.SPWeb}) + 0x8e bytes
Microsoft.SharePoint.dll!Microsoft.SharePoint.WebPartPages.WebPartImporter.Import(Microsoft.SharePoint.WebPartPages.SPWebPartManager manager = {Microsoft.SharePoint.WebPartPages.SPWebPartManager}, System.Xml.XmlReader reader = {None}, bool clearConnections = true, Microsoft.SharePoint.SPWeb spWeb = {Microsoft.SharePoint.SPWeb}) + 0xa1 bytes
Microsoft.SharePoint.dll!Microsoft.SharePoint.WebPartPages.WebPartQuickAdd.System.Web.UI.IPostBackEventHandler.RaisePostBackEvent(string eventArgument = "http%253A%252F%252Fv%252Dsp2007%252F%255Fcatalogs%252Fwp%252FClientSideDocumentsWebPart%252Ewebpart;ClientSideDocumentsWebPart") + 0x288 bytes
System.Web.dll!System.Web.UI.Page.RaisePostBackEvent(System.Web.UI.IPostBackEventHandler sourceControl, string eventArgument) + 0xc bytes
System.Web.dll!System.Web.UI.Page.RaisePostBackEvent(System.Collections.Specialized.NameValueCollection postData) + 0xb2 bytes
...the rest of the stack is the same as when opening a page normally.
Try setting up a solution package to deploy code access security settings. You definitely need SqlClientPermission. Check out my post on Code Access Security for web parts for more information.
Just as a reference for the next ones coming, here there's one of the many articles were code in web part constructor is marked as a big NO-NO.
That is odd. Maybe you could special case your web part to not do the database call when the page is in edit/design mode. Wouldn't that fix your problem?
As a simple test, you could deploy the assemby containing the web part into the GAL. There it will run with Full Trust.
Personally, I would not recommend establishing a database connection in the constructor of a web part unless you had a compelling reason to do so.
[updated 3009-03-27]
Debugging is often about ruling out causes. Even though you believe the web part is running in Full Trust, I recommend testing the GAC'ed case. Remember to remove the .dll from the Bin directory for the test. This will only take 5-10 minutes and you'll know where you stand.
My solution was to move the data access code to the OnInit method, but that is irritating. Does anyone have any insight?
When SharePoint is going through and processing the request the first thing that it will be doing is executing your constructor to create a new instance of the object. The Constructors that it calls are parameterless so that they can be serialized and deserialized for import/exports. Inside of the constructor none of the security constructs or associated objects have been set in the newly created object. It may therefore be the case that your object does not have any context information about where it is living or what it is doing.
By moving your code into the OnInit method you have shifted the time of execution back as some of your related objects and what not have been bound automatically by this point. In the ASP.net lifecycle, OnInit methods work from the from the top down and OnLoad methods work from the bottom up. So that may also influence whether your parent or children have had their related code executed yet.

Resources