But I have never really found a full answer. I'm gonna try to give a full one!
First, be aware, that there are many ways to catch the SharePoint errors, but to my knowledge, only this one is fully supporter by Microsoft, cause it uses an HTTPModule which is a supported way of working!
1/ Create your HTTPModule
The class you are about to create inherits System.Web.IHttpModule
During the Init of the module, add an event handler that will listen to the Error. It should be something like
public void Init(HttpApplication Context)
{
Context.Error += new EventHandler(Application_Error);
}
And now declare your event handler function:
public void Application_Error(object sender, EventArgs e)
{
HttpContext Context = HttpContext.Current;
Exception MyExc;
for (MyExc= Context.Server.GetLastError();
exception.InnerException != null;
exception = exception.InnerException) { }
String errorCode = DateTime.Now.ToString("ddMMyyyy-HHmmfff");
String errorMessage = MyExc.Message.ToString();
String errorStackTrace = MyExc.StackTrace.ToString();
HttpContext.Current.Server.ClearError();
HttpContext.Current.Response.Clear();
HttpContext.Current.Application.Clear();
HttpContext.Current.Application.Add("LastException", MyExc);
HttpContext.Current.Application.Add("ErrorMessage", errorMessage);
HttpContext.Current.Application.Add("ErrorCode", errorCode);
HttpContext.Current.Application.Add("ErrorStackTrace", errorStackTrace);
((System.Web.HttpApplication)(sender)).Response.Redirect("/_layouts/ErrorBranding/MyErrorHandler.aspx");
}
I was basically doing it differently, using an arrey of AllErrors, but it didn't give always the good exception, so I used a part of the code created by Anupam Ranku on his blog http://www.codeproject.com/KB/sharepoint/Handling_Error_Centrally.aspx.
From him, I took the fact that using
for (MyExc= Context.Server.GetLastError();exception.InnerException != null;exception = exception.InnerException) { }
2/ Create an Error page
On the Page_Load of this page, just verify that the last exception exists
if (!Page.IsPostBack)In this page, you can use your already defined
{
if (HttpContext.Current.Application.Get("LastException") != null)
{
//your handler
}
}HttpContext.Current.Application.Get("errorCode");
HttpContext.Current.Application.Get("errorMessage");
HttpContext.Current.Application.Get("errorStackTrace");
Design your page the way you want it to be!
3/ Modify your web.config
For this, let's assume that you have created a feature, and you have already a classe inheriting
SPFeatureReceiver.
So of course you have already created your 4 overidden functions (
FeatureActivated,
FeatureDeactivating,
FeatureInstalled,
FeatureUninstalling)
The FeatureActivated method will be launched after activation of the feature (smart name for a method that do so!!!), so what you want to do is to add your http module to the web.config (Carreful: it must be added to ALL the web servers of your farm), to do this let's use this :
private string _OWNER = "FTErrorBranding";
private string httpModuleValue = "MyNamespace.MyClass, MyAssembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=bce1c40c0905a9da";
public override void FeatureActivated(SPFeatureReceiverProperties properties)
{
try
{
SPWebApplication webApp = properties.Feature.Parent as SPWebApplication;
webApp.WebConfigModifications.Clear();
AddNewHttpModule(webApp.WebConfigModifications, "ErrorCustomization", httpModuleValue);
webApp.Update();
webApp.Farm.Services.GetValue().ApplyWebConfigModifications();
}
catch (Exception ex)
{
throw new Exception(ex.Message);
}
}
private void AddNewHttpModule(Collection allModifications, string name, string value)
{
SPWebConfigModification modification = new SPWebConfigModification(string.Format
("add[@name='{0}']", name), "configuration/system.web/httpModules");
modification.Type = SPWebConfigModification.SPWebConfigModificationType.EnsureChildNode;
modification.Owner = _OWNER;
modification.Value = string.Format(CultureInfo.InvariantCulture, string.Format("", name, value));
if (allModifications.Contains(modification))
{
allModifications.Remove(modification);
}
allModifications.Add(modification);
}
To conclude, See the image of my VS project, in order to understand the wya the project is built (I'm addicted to WSPBuilder!)
4/ Addendum -April 2009 - Catch WebParts Error
So far, the feature worked almost perfectly. I only add one issue with Webpart errors. SharePoint, on the error page sometime add a link to go to the Webpart management page. The HttpModule can't see the difference between those kind of errors and others...(until now) !!
I have added a function in the httpModule that recognize whether an exception has been thrown from a webpart or not... here it is!
private bool IsWebPartOnExceptionStack(Exception e)
{
StackTrace trace = new StackTrace(e);
int index = 0;
while (index <>
{
Type declaringType = trace.GetFrame(index).GetMethod().DeclaringType;
if (!typeof(WebPart).IsAssignableFrom(declaringType))
{
index++;
continue;
}
else
return true;
}
}
}
At the end of the Application_Error method, just add a new Application variable :
HttpContext.Current.Application.Add("ISWPError", IsWebPartOnExceptionStack(exception));
In your error page, you just have to add a if then else, to manage this case.
No comments:
Post a Comment