I am seeing some very odd behavior when trying to do a redirect with .NET MVC. I read somewhere to not do the redirect in a subroutine so I changed that part of the code, but I am still having the problem. This only happens in production (particularly with bots), and I can't reproduce it in the dev environment. I added in some logging to try to help but still don't understand what is happening (it was a poor man's solution because I don't have access to put debug symbols on the production server). The call stack doesn't even make sense because it says there is a recursive call that doesn't exist. Thanks in advance for any help!
Error details:
Step Number: 16, LangID: 1033, Language: en, Culture: us -
System.NullReferenceException: Object reference not set to an instance of an object. at [REMOVED]_Web.Controllers.MVC.HomeController.setLanguage(String language, String _culture)User Name: Anonymous
URL: [REMOVED]'A=0
User Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; pt-PT; rv:1.9.1.2) Gecko/20090729 Firefox/3.5.2 (.NET CLR 3.5.30729)
Exception Details:System.Exception: Step Number: 16, LangID: 1033, Language: en, Culture: us - System.NullReferenceException: Object reference not set to an instance of an object.
at [REMOVED]_Web.Controllers.MVC.HomeController.setLanguage(String language, String _culture)
at [REMOVED]_Web.Controllers.MVC.HomeController.setLanguage(String language, String _culture)
at [REMOVED]_Web.Controllers.MVC.HomeController.Init(String language, String culture)
at [REMOVED]_Web.Controllers.MVC.HomeController.ProdCatSearch(String language, String culture)
at lambda_method(Closure , ControllerBase , Object[] )
at System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary2 parameters)
at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary2 parameters)
at System.Web.Mvc.Async.AsyncControllerActionInvoker.b__39(IAsyncResult asyncResult, ActionInvocation innerInvokeState)
at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResult2.CallEndDelegate(IAsyncResult asyncResult)
at System.Web.Mvc.Async.AsyncControllerActionInvoker.AsyncInvocationWithFilters.b__3d()
at System.Web.Mvc.Async.AsyncControllerActionInvoker.AsyncInvocationWithFilters.<>c__DisplayClass46.b__3f()
at System.Web.Mvc.Async.AsyncControllerActionInvoker.<>c__DisplayClass33.b__32(IAsyncResult asyncResult)
at System.Web.Mvc.Async.AsyncControllerActionInvoker.<>c__DisplayClass21.<>c__DisplayClass2b.b__1c()
at System.Web.Mvc.Async.AsyncControllerActionInvoker.<>c__DisplayClass21.b__1e(IAsyncResult asyncResult)
at System.Web.Mvc.Controller.b__1d(IAsyncResult asyncResult, ExecuteCoreState innerState)
at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult)
at System.Web.Mvc.Controller.EndExecuteCore(IAsyncResult asyncResult)
at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncVoid1.CallEndDelegate(IAsyncResult asyncResult)
at System.Web.Mvc.MvcHandler.b__5(IAsyncResult asyncResult, ProcessRequestState innerState)
at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncVoid1.CallEndDelegate(IAsyncResult asyncResult)
at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)
Source code:
Private Sub setLanguage(language As String, _culture As String)
Dim stepNumber As Integer = 0
Try
Dim langCookie As HttpCookie
Dim hasException As Boolean = False
Try
If (String.IsNullOrEmpty(language) OrElse String.IsNullOrEmpty(_culture)) Then
language = "en"
_culture = "us"
End If
stepNumber = 1
Dim languages = clsAppSettings.Instance.GetAppSettingTable(Of String)("Language")
For Each lang In languages
supportedLangs.Add(New LanguageInfo(lang))
Next
supportedLangs.Sort(Function(x, y) x.SortOrder.CompareTo(y.SortOrder))
langCookie = HttpContext.Request.Cookies.Get("langID")
stepNumber = 2
If langCookie IsNot Nothing AndAlso Not String.IsNullOrWhiteSpace(langCookie.Value) Then
stepNumber = 3
LangId = langCookie.Value
CultureInfo.CreateSpecificCulture(language + "-" + _culture)
stepNumber = 4
Else
stepNumber = 5
Dim culture As CultureInfo
If language.ToLower = "en" And _culture.ToLower = "us" Then
stepNumber = 6
Dim langIdFromBrowser As String = String.Empty
Dim browserLangs = Request.UserLanguages
For Each browserLang In browserLangs
culture = CultureInfo.CreateSpecificCulture(browserLang.ToLowerInvariant().Trim())
langIdFromBrowser = culture.LCID.ToString
If Not String.IsNullOrWhiteSpace(langIdFromBrowser) Then
If (From items In supportedLangs Where items.Id = CInt(langIdFromBrowser)).Any Then
LangId = langIdFromBrowser
Exit For
End If
End If
Next
stepNumber = 7
If String.IsNullOrEmpty(LangId) Then
LangId = "1033"
End If
Else
stepNumber = 8
culture = CultureInfo.CreateSpecificCulture(language + "-" + _culture)
LangId = culture.LCID.ToString
If Not String.IsNullOrWhiteSpace(LangId) Then
If Not (From items In supportedLangs Where items.Id = CInt(LangId)).Any Then
LangId = "1033"
End If
End If
stepNumber = 9
End If
' Correct for the fact that SharePoint uses Spanish Traditional vs Spanish Modern Sort
If LangId = "1034" Then
LangId = "3082"
End If
stepNumber = 10
End If
Catch ex As CultureNotFoundException
stepNumber = 11
If String.IsNullOrEmpty(LangId) Then
LangId = "1033"
End If
hasException = True
Finally
' Final check to ensure NO empty value ever makes it past this point.
If String.IsNullOrWhiteSpace(LangId) Then
LangId = "1033"
End If
langCookie = New HttpCookie("langID", LangId)
langCookie.Expires = Date.Now().AddYears(1)
Web.HttpContext.Current.Response.Cookies.Add(langCookie)
stepNumber = 12
If hasException OrElse CultureInfo.CreateSpecificCulture(language + "-" + _culture).LCID.ToString() <> LangId Then
stepNumber = 13
Dim newCulture As New CultureInfo(CInt(LangId))
stepNumber = 14
Dim cultureValues As String() = newCulture.Name.Split("-"c)
Dim rUrl As String = Request.Url().OriginalString()
Dim replacement As String = (cultureValues(0) + "-" + cultureValues(1)).ToLower()
rUrl = rUrl.Replace((language + "-" + _culture), replacement)
'Response.Redirect(rUrl, False)
'HttpContext.ApplicationInstance.CompleteRequest()
End If
stepNumber = 15
ViewData("SelectedLang") = LangId
ViewData("SupportedLangs") = supportedLangs
transObj = Translations.GetTranslations(LangId)
ViewData("Translations") = New JavaScriptSerializer().Serialize(transObj)
stepNumber = 16
End Try
Catch ex As Exception
Throw New Exception(String.Format("Step Number: {0}, LangID: {1}, Language: {2}, Culture: {3} - {4}", stepNumber, LangId, language, _culture, ex.ToString()))
End Try
End Sub
catch
block from earlier in the script, will it re-enter the inner finally block before leaving the function? I assume since the inner exception is only catching theCultureNotFoundException
that the outer catch would have to be the one catching theNullReferenceException
? If so, does that catch execute and then step back into the finally block? I'm not familiar enough with the execution path regarding .NET exceptions. – War10ck