Write a caught ASP.NET exception to EventLog without losing detail - c#

This article explains in detail how to log an ASP.NET exception to the Windows EventLog and display a custom error page to the end-user.
However, the standard Event Logging mechanism for an ASP.NET web application automatically includes a lot of useful information not shown in this article. Implementing the code in the article results in a loss of detail/granularity in my error Event.
For example with automatic uncaught exception logging, you can see many attributes under the headings: Event Information, Application Information, Process Information, Request Information, Thread Information, Custom Event Details.
How can I implement logging of all of the same information that is logged in an uncaught exception and append my custom information into the section Custom Event Details? The best answer should preferably use some inbuilt method(s) of System.Diagnostics or System.Exception or similar i.e. writing as little code as possible to write the log entry with all sections mentioned above and simply append any custom details to the string.
If it is possible, I would also like to return the unique hashed Event ID (example b68b3934cbb0427e9497de40663c5225 from below) back to the application for display on my ErrorPage.aspx
Example of log format required:
Event code: 3005
Event message: An unhandled exception has occurred.
Event time: 15/07/2016 15:44:01
Event time (UTC): 15/07/2016 14:44:01
Event ID: b68b3934cbb0427e9497de40663c5225
Event sequence: 131
Event occurrence: 2
Event detail code: 0
Application information:
Application domain: /LM/W3SVC/3/ROOT-1-131130657267252632
Trust level: Full
Application Virtual Path: /
Application Path: C:\WWW\nobulus\nobulusPMM\Application\PMM\
Machine name: L-ADAM
Process information:
Process ID: 47216
Process name: iisexpress.exe
Account name: L-ADAM\Adam
Exception information:
Exception type: ApplicationException
Exception message: Error running stored procedure saveValidation: Procedure or function 'saveValidation' expects parameter '#ValidatedBy', which was not supplied.
at PMM.Models.PMM_DB.runStoredProcedure(String StoredProcedureName, List`1 SQLParameters) in C:\WWW\nobulus\nobulusPMM\Application\PMM\Models\PMM_DB.cs:line 104
at PMM.Models.PMM_DB.saveValidation(String PTLUniqueID, String ValidatedBy, DateTime ValidationDateTime, Nullable`1 ValidationCategoryID, String ValidationCategory, String Comment, Nullable`1 ClockStartDate, Nullable`1 ClockStopDate, String StartRTTStatus, String StopRTTStatus, String LastRTTStatus, Boolean MergedPathway, String MergedPathwayID, String ExtinctPathwayID, DataTable ChecklistResponses) in C:\WWW\nobulus\nobulusPMM\Application\PMM\Models\PMM_DB.cs:line 265
at PMM.Validate.lnkSaveButton_Click(Object sender, EventArgs e) in C:\WWW\nobulus\nobulusPMM\Application\PMM\Validate.aspx.cs:line 323
at System.Web.UI.WebControls.LinkButton.OnClick(EventArgs e)
at System.Web.UI.WebControls.LinkButton.RaisePostBackEvent(String eventArgument)
at System.Web.UI.WebControls.LinkButton.System.Web.UI.IPostBackEventHandler.RaisePostBackEvent(String eventArgument)
at System.Web.UI.Page.RaisePostBackEvent(IPostBackEventHandler sourceControl, String eventArgument)
at System.Web.UI.Page.RaisePostBackEvent(NameValueCollection postData)
at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
Request information:
Request URL: http://localhost:6901/Validate?PTLUniqueID=RTT10487
Request path: /Validate
User host address: ::1
User: L-ADAM\Adam
Is authenticated: True
Authentication Type: Negotiate
Thread account name: L-ADAM\Adam
Thread information:
Thread ID: 19
Thread account name: L-ADAM\Adam
Is impersonating: False
Stack trace: at PMM.Models.PMM_DB.runStoredProcedure(String StoredProcedureName, List`1 SQLParameters) in C:\WWW\nobulus\nobulusPMM\Application\PMM\Models\PMM_DB. cs:line 104
at PMM.Models.PMM_DB.saveValidation(String PTLUniqueID, String ValidatedBy, DateTime ValidationDateTime, Nullable`1 ValidationCategoryID, String ValidationCategory, String Comment, Nullable`1 ClockStartDate, Nullable`1 ClockStopDate, String StartRTTStatus, String StopRTTStatus, String LastRTTStatus, Boolean MergedPathway, String MergedPathwayID, String ExtinctPathwayID, DataTable ChecklistResponses) in C:\WWW\nobulus\nobulusPMM\Application\PMM\Models\PMM_DB.cs:line 265
at PMM.Validate.lnkSaveButton_Click(Object sender, EventArgs e) in C:\WWW\nobulus\nobulusPMM\Application\PMM\Validate.aspx.cs:line 323
at System.Web.UI.WebControls.LinkButton.OnClick(EventArgs e)
at System.Web.UI.WebControls.LinkButton.RaisePostBackEvent(String eventArgument)
at System.Web.UI.WebControls.LinkButton.System.Web.UI.IPostBackEventHandler.RaisePostBackEvent(String eventArgument)
at System.Web.UI.Page.RaisePostBackEvent(IPostBackEventHandler sourceControl, String eventArgument)
at System.Web.UI.Page.RaisePostBackEvent(NameValueCollection postData)
at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
Custom event details:

UPDATE
I actually found out using ILSpy and roaming in different framework classes that ASP.NET uses internally WebErrorEvent, which possess protected methods to achieve the same behavior.
Solution 1:
For that, just create a class which inherits WebErrorEvent, and then override its constructor:
public class CustomWebErrorEvent : WebErrorEvent
{
public CustomWebErrorEvent(string message, EventSource source, int eventCode, Exception ex) : base(message, source, eventCode, ex)
{
}
}
Then using it inside the Error management method from Global.asax:
protected void Application_Error(Object sender, EventArgs e)
{
// Log error to the Event Log
Exception myError = null;
if (HttpContext.Current.Server.GetLastError() != null)
{
var r = new CustomWebErrorEvent("error", null, 120, HttpContext.Current.Server.GetLastError());
}
}
I am pretty sure it is posslbe also to overload ASPNET to only raise straight a custom WebErrorEvent, but I didn't find it yet.
I am still trying to figure out how to add custom info to the event as overriding the method FormatCustomEventDetails is not getting called for Web Managed error events.
Solution 2:
If not possible as missing adding custom fields for now, you can use a similar method that I wrote which does the same output:
// Log error to the Event Log
Exception myError = null;
if (HttpContext.Current.Server.GetLastError() != null)
{
var request = HttpContext.Current.Request;
myError = HttpContext.Current.Server.GetLastError();
var dateAsBytes = System.Text.Encoding.UTF8.GetBytes(DateTime.Now.ToString("G"));
var id = Convert.ToBase64String(System.Security.Cryptography.MD5.Create().ComputeHash(dateAsBytes));
// Event info:
var eventMessage = myError.Message;
var currentTime = DateTime.Now.ToString("G");
var currentTimeUTC = DateTime.UtcNow.ToString("G");
// Application info:
var appDomainName = AppDomain.CurrentDomain.FriendlyName;
var appDomainTrustLevel = (AppDomain.CurrentDomain.IsFullyTrusted) ? "Full" : "Partial";
var appVirtualPath = VirtualPathUtility.GetDirectory(request.Path);
var appPath = request.PhysicalApplicationPath;
var machineName = Environment.MachineName;
// Process info:
var process = Process.GetCurrentProcess();
var processId = process.Id;
var processName = process.ProcessName;
var user = System.Security.Principal.WindowsIdentity.GetCurrent().User;
var accountName = user.Translate(typeof(System.Security.Principal.NTAccount));
// Exception info:
var exceptionType = myError.GetType().FullName;
var exceptionMessage = myError.Message;
var exceptionStack = myError.StackTrace;
// Request info:
var url = request.Url.AbsoluteUri;
var urlPath = request.Url.PathAndQuery;
var remoteAddress = request.UserHostAddress;
var userName = System.Security.Principal.WindowsIdentity.GetCurrent().Name;
var isAuthenticated = HttpContext.Current.User.Identity.IsAuthenticated;
var authenticationType = System.Security.Principal.WindowsIdentity.GetCurrent().AuthenticationType;
// Thread info:
var impersonationLevel = System.Security.Principal.WindowsIdentity.GetCurrent().ImpersonationLevel;
var exceptionStack2 = myError.StackTrace;
// TODO: aggregate all info as string before writting to EventLog.
}
I found using existing .NET Apis almost all required fields from your output, just needed know to be aggregated as a string before outputting it in EventLog.
You can see that some of the object I am using (such as AppDomain.CurrentDomain, HttpContext.Current.Request or Process.GetCurrentProcess() returns a lot of other info, which could also ne added to the output if needed.
This all can be wrapped up under a method for code brevity of course.

Related

Keep getting "The payload was invalid" exception from ProtectedBrowserStorage

In my .NET 5 Blazor Server Application I add dataprotection to my services using the following line in my Program.cs
builder.Services.AddDataProtection()
.SetApplicationName("WhateverApplicationName")
.PersistKeysToDbContext<KpaContext>();
Now when I try to get data from ProtectedLocalStorage using this code
try
{
var sessionid = await ProtectedLocalStorage.GetAsync<Guid>("BrowserId");
}
catch(Exception ex)
{
Debugger.Break();
}
It keeps throwing this error:
System.Security.Cryptography.CryptographicException: The payload was
invalid.
at
Microsoft.AspNetCore.DataProtection.Managed.ManagedAuthenticatedEncryptor.Decrypt(ArraySegment1 protectedPayload, ArraySegment1 additionalAuthenticatedData) at
Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingBasedDataProtector.UnprotectCore(Byte[]
protectedData, Boolean allowOperationsOnRevokedKeys, UnprotectStatus&
status) at
Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingBasedDataProtector.Unprotect(Byte[]
protectedData) at
Microsoft.AspNetCore.DataProtection.DataProtectionCommonExtensions.Unprotect(IDataProtector
protector, String protectedData) at
Microsoft.AspNetCore.Components.Server.ProtectedBrowserStorage.ProtectedBrowserStorage.GetAsync[TValue](String
purpose, String key)
The application runs on a docker container.
The table DataProtectionKeys contains a record of a key which is valid from 05-07 till 03-10 so the key should be active.
What am I doing wrong. I used this link to configure data protection:
https://learn.microsoft.com/en-us/aspnet/core/security/data-protection/configuration/overview?view=aspnetcore-6.0

Merging WCF webservice to my web application returns an exception

I would like to add an reference for WCF weather forecast webservice in my application.The thing is I have done everything correctly,but i am lacking somewhere else.It throws an Exception.The Exception message is in the bottom of this post.Somebody out there please help me to fix this.Unles or until fixing this i couln't move to the next phase.
My Source Code is here:
public partial class Testing : System.Web.UI.Page
{
weather.WeatherForecastServiceClient ws = new weather.WeatherForecastServiceClient();
protected void Page_Load(object sender, EventArgs e)
{
SortedDictionary<string, string> objDic = new SortedDictionary<string, string>();
foreach (CultureInfo ObjectCultureInfo in CultureInfo.GetCultures(CultureTypes.SpecificCultures))
{
RegionInfo objRegionInfo = new RegionInfo(ObjectCultureInfo.Name);
if (!objDic.ContainsKey(objRegionInfo.EnglishName))
{
objDic.Add(objRegionInfo.EnglishName, ObjectCultureInfo.Name);
}
}
foreach (KeyValuePair<string, string> val in objDic)
{
Country.Items.Add(new ListItem(val.Key, val.Value));
}
}
protected void callwebservice_Click(object sender, EventArgs e)
{
Result.Text = "Result" + ws.GetForecastByCity(City.SelectedItem.ToString(), Country.SelectedItem.ToString());
}
protected void Country_SelectedIndexChanged(object sender, EventArgs e)
{
string[] cities = ws.GetCitiesByCountry(Country.SelectedItem.ToString());
City.DataSource = cities;
City.DataBind();
}
}
This is my Exception
Server Error in '/' Application.
**The server was unable to process the request due to an internal error. For more information about the error, either turn on IncludeExceptionDetailInFaults (either from ServiceBehaviorAttribute or from the <serviceDebug> configuration behavior) on the server in order to send the exception information back to the client, or turn on tracing as per the Microsoft .NET Framework 3.0 SDK documentation and inspect the server trace logs.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.ServiceModel.FaultException: The server was unable to process the request due to an internal error. For more information about the error, either turn on IncludeExceptionDetailInFaults (either from ServiceBehaviorAttribute or from the <serviceDebug> configuration behavior) on the server in order to send the exception information back to the client, or turn on tracing as per the Microsoft .NET Framework 3.0 SDK documentation and inspect the server trace logs.
Source Error:
Line 310:
Line 311: public testing.weather.Weather GetForecastByCity(string City, string Country) {
Line 312: return base.Channel.GetForecastByCity(City, Country);
Line 313: }
Line 314: }
Source File: E:\***\WeatherForecast\testing\Service References\weather\Reference.cs Line: 312
Stack Trace:
[FaultException: The server was unable to process the request due to an internal error. For more information about the error, either turn on IncludeExceptionDetailInFaults (either from ServiceBehaviorAttribute or from the <serviceDebug> configuration behavior) on the server in order to send the exception information back to the client, or turn on tracing as per the Microsoft .NET Framework 3.0 SDK documentation and inspect the server trace logs.]
System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg) +9442991
System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type) +345
testing.weather.IWeatherForecastService.GetForecastByCity(String City, String Country) +0
testing.weather.WeatherForecastServiceClient.GetForecastByCity(String City, String Country) in E:\sasi\WeatherForecast\testing\Service References\weather\Reference.cs:312
testing.Testing.callwebservice_Click(Object sender, EventArgs e) in E:\sasi\WeatherForecast\testing\Testing.aspx.cs:40
System.Web.UI.WebControls.Button.OnClick(EventArgs e) +118
System.Web.UI.WebControls.Button.RaisePostBackEvent(String eventArgument) +112
System.Web.UI.WebControls.Button.System.Web.UI.IPostBackEventHandler.RaisePostBackEvent(String eventArgument) +10
System.Web.UI.Page.RaisePostBackEvent(IPostBackEventHandler sourceControl, String eventArgument) +13
System.Web.UI.Page.RaisePostBackEvent(NameValueCollection postData) +36
System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +5563
Version Information: Microsoft .NET Framework Version:4.0.30319; ASP.NET Version:4.0.30319.272**
You have implemented the service correctly. You can confirm this by running GetCitiesByCountry (it will return a list of cities). It is just that the method GetForecastByCity does not currently work.
Try any of these APIs instead.

Problems in aspnet membership provider

I am using asp.net memebership
I log out the applcation by writting this code for log out
if (Membership.GetUser(HttpContext.Current.User.Identity).IsOnline) ;
{
FormsAuthentication.SignOut();
Response.Redirect(FormsAuthentication.LoginUrl);
}
Response.Redirect("loginpage.aspx");
After then I started the application and gettig the error in code block of authetication .below I am writtng a code and error message
else if (User.Identity.IsAuthenticated == true && Membership.GetUser( Membership.FindUsersByName(User.Identity.Name)).IsOnline==true)
{
FormsAuthentication.SignOut();
FormsAuthentication.RedirectToLoginPage();
MembershipUser currUser = null;
string gt = null;
if (HttpContext.Current.User != null)
{
currUser = Membership.GetUser(true);
gt = currUser.Email;
}
/// string temp = User.Identity.GetProfile().ID;
//string query = "Insert into user_tbl(MemberID)(" + temp + ")";
//Response.Redirect("UserPanel.aspx");
//return;
}
here Membership.FindUsersByName(User.Identity.Name)).IsOnline==true) I am getting this error
[ArgumentException: The provider user key supplied is invalid. It
must be of type System.Guid. Parameter name: providerUserKey]
I am unable to find what to do , I debug the application and found User.Identity.Name as a hash value
Stack Trace
Exception Details: System.ArgumentException: The provider user key supplied is invalid. It must be of type System.Guid.
Parameter name: providerUserKey
Source Error:
Line 86: }
Line 87:
Line 88: else if (User.Identity.IsAuthenticated == true && Membership.GetUser( Membership.FindUsersByName(User.Identity.Name)).IsOnline==true)
Line 89: {
Line 90:
Source File: d:\31 May 2012\Demo\LoginPage.aspx.cs Line: 88
Stack Trace:
[ArgumentException: The provider user key supplied is invalid. It must be of type System.Guid.
Parameter name: providerUserKey]
System.Web.Security.SqlMembershipProvider.GetUser(Object providerUserKey, Boolean userIsOnline) +2242996
System.Web.Security.Membership.GetUser(Object providerUserKey, Boolean userIsOnline) +40
System.Web.Security.Membership.GetUser(Object providerUserKey) +6
LoginPage.Page_Load(Object sender, EventArgs e) in d:\31 May 2012\Demo\LoginPage.aspx.cs:88
System.Web.Util.CalliHelper.EventArgFunctionCaller(IntPtr fp, Object o, Object t, EventArgs e) +15
System.Web.Util.CalliEventHandlerDelegateProxy.Callback(Object sender, EventArgs e) +36
System.Web.UI.Control.OnLoad(EventArgs e) +92
System.Web.UI.Control.LoadRecursive() +54
System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +772
Or you could also use Request.IsAuthenticated which dosent get the whole user object and just checks authentication.
According to Visual Studio, Membership.FindUsersByName returns MembershipUserCollection. You pass that object to the Membership.GetUser method, which does accept a parameter of the object type, but that object is supposed to be a user's ID (a GUID in ASP.NET). So, the exception is quite expected: you're trying to pass a collection of users, while the method expects a single user ID.
If you need to check whether a user is currently logged in, you can simply do this:
if (Membership.GetUser() != null)
See this MSDN Library article for more information on the method.

DirectoryEntry.Children.Remove throws "unspecified error"

I have a little code to delete a security group from Active Directory, but when run, I get a COMException with the message "Unspecified error".
Here is the code:
public void DeleteGroup(Model.Asset pADSecurityGroup)
{
using(DirectoryEntry ou = new DirectoryEntry(pADSecurityGroup.Organization.ActiveDirectoryMappings.Single().Identifier))
using(DirectoryEntry group = new DirectoryEntry("LDAP://" + pADSecurityGroup.ActiveDirectoryMappings.Single().Identifier))
{
ou.Children.Remove(group);
group.CommitChanges();
}
}
And here's the message in the Windows Event Console:
Event code: 3005
Event message: An unhandled exception has occurred.
Event time: 8/23/2011 11:29:35 AM
Event time (UTC): 8/23/2011 5:29:35 PM
Event ID: 67e6356c9ff146c7a0d9024350cbb3a0
Event sequence: 79
Event occurrence: 1
Event detail code: 0
Application information:
Application domain: /LM/W3SVC/1/ROOT-2-129585938920392018
Trust level: Full
Application Virtual Path: /
Application Path: C:\inetpub\wwwroot\vo\Web\Portal\
Machine name: TR-2K8-001 Process information:
Process ID: 8348
Process name: w3wp.exe
Account name: VO\treed Exception information:
Exception type: COMException
Exception message: Unspecified error
at System.DirectoryServices.DirectoryEntry.Bind(Boolean throwIfFail)
at System.DirectoryServices.DirectoryEntry.Bind()
at System.DirectoryServices.DirectoryEntry.get_IsContainer()
at System.DirectoryServices.DirectoryEntries.Remove(DirectoryEntry entry)
at VirtualOffice.DirectoryServices.Impl.DirectoryService.DeleteGroup(ResourcePool pResourcePool) in C:\inetpub\wwwroot\vo\Common Libraries\VirtualOffice.DirectoryServices\Impl\DirectoryService.cs:line 249
at VirtualOffice.Controllers.ResourcePoolController.Delete(Int32 pServiceProviderId) in C:\inetpub\wwwroot\vo\Common Libraries\VirtualOffice.Controllers\ResourcePoolController.cs:line 171
at Organization_ResourcePools.rtbResourcePools_OnButtonClick(Object sender, RadToolBarEventArgs e) in c:\inetpub\wwwroot\vo\Web\Portal\Organization\ResourcePools.aspx.cs:line 85
at Telerik.Web.UI.RadToolBar.OnButtonClick(RadToolBarEventArgs e)
at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
Request information:
Request URL: https://localhost:443/Organization/ResourcePools.aspx
Request path: /Organization/ResourcePools.aspx
User host address: ::1
User: Portal Admin
Is authenticated: True
Authentication Type: Federation
Thread account name: VO\treed Thread information:
Thread ID: 5
Thread account name: VO\treed
Is impersonating: False
Stack trace:
at System.DirectoryServices.DirectoryEntry.Bind(Boolean throwIfFail)
at System.DirectoryServices.DirectoryEntry.Bind()
at System.DirectoryServices.DirectoryEntry.get_IsContainer()
at System.DirectoryServices.DirectoryEntries.Remove(DirectoryEntry entry)
at VirtualOffice.DirectoryServices.Impl.DirectoryService.DeleteGroup(ResourcePool pResourcePool) in C:\inetpub\wwwroot\vo\Common Libraries\VirtualOffice.DirectoryServices\Impl\DirectoryService.cs:line 249
at VirtualOffice.Controllers.ResourcePoolController.Delete(Int32 pServiceProviderId) in C:\inetpub\wwwroot\vo\Common Libraries\VirtualOffice.Controllers\ResourcePoolController.cs:line 171
at Organization_ResourcePools.rtbResourcePools_OnButtonClick(Object sender, RadToolBarEventArgs e) in c:\inetpub\wwwroot\vo\Web\Portal\Organization\ResourcePools.aspx.cs:line 85
at Telerik.Web.UI.RadToolBar.OnButtonClick(RadToolBarEventArgs e)
at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
Custom event details:
Based on the questions/answer in the comments section I revise my answer.
I think you simply forgot the LDAP protocol identifier for the LDAP path of your organization unit. I think, unspecified error means invalid LDAP path.
Try the following code:
public void DeleteGroup(Model.Asset pAsset)
{
using(DirectoryEntry ou = new DirectoryEntry("LDAP://" + pResourcePool.Organization.ActiveDirectoryMappings.Single().Identifier))
{
using(DirectoryEntry group = new DirectoryEntry("LDAP://" + pResourcePool.ActiveDirectoryMappings.Single().Identifier), username, userpwd)
{
ou.Children.Remove(group);
group.CommitChanges();
}
}
}
By the same token, ensure that the LDAP protocol identifier is written using capital letters.
Hope, this helps.
Just guessing: Maybe the DirectoryEntry "ou" is not empty.
MSDN says:
If the entry to be removed is a container, the container must be empty. To delete a container and all its children, use the DeleteTree method.
You also may try to catch the ComException and gather more information so the problem can be analysed.

Connecting to new Facebook Client with access token

I finally got the right Facebook access token generated from the code. However now I have another problem. Using that access token to fetch user data. Every time I use the token to fetch data, it returns with an exception !String.IsNullOrEmpty(accessToken).
Full stack Trace:
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.Diagnostics.Contracts.__ContractsRuntime+ContractException: Precondition failed: !string.IsNullOrEmpty(accessToken)
Source Error:
An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.
Stack Trace:
[ContractException: Precondition failed: !string.IsNullOrEmpty(accessToken)]
Facebook.Web.FacebookWebClient..ctor(String accessToken) +137
Facebook_Photo_App._Default.Button1_Click(Object sender, EventArgs e) in Default.aspx.cs:105
System.EventHandler.Invoke(Object sender, EventArgs e) +0
System.Web.UI.WebControls.Button.OnClick(EventArgs e) +118
System.Web.UI.WebControls.Button.RaisePostBackEvent(String eventArgument) +112
System.Web.UI.WebControls.Button.System.Web.UI.IPostBackEventHandler.RaisePostBackEvent(String eventArgument) +10
System.Web.UI.Page.RaisePostBackEvent(IPostBackEventHandler sourceControl, String eventArgument) +13
System.Web.UI.Page.RaisePostBackEvent(NameValueCollection postData) +36
System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +5563
Version Information: Microsoft .NET Framework Version:4.0.30319; ASP.NET Version:4.0.30319.1
My code:
To generate the access token on the page load:
string code;
code = Request.QueryString["code"];
//TextBox1.Text = code;
string token;
string url = "https://graph.facebook.com/oauth/access_token?client_id=XXX&redirect_uri=http://apps.facebook.com/dutch-vegas/&client_secret=XXX&code=" + code;
WebRequest request = WebRequest.Create(url);
WebResponse response = request.GetResponse();
StreamReader reader = new StreamReader(response.GetResponseStream());
token = reader.ReadToEnd();
string decodedtoken = token;
TextBox1.Text = decodedtoken;
decodedtoken = decodedtoken.Replace("access_token=", "");
int start = decodedtoken.IndexOf("&");
int count = decodedtoken.Length - decodedtoken.IndexOf("&");
decodedtoken = decodedtoken.Remove(start, count);
On the button implement the Access token to fetch user data
var client = new FacebookClient(decodedtoken);
dynamic me = client.Get("me");
string email = me.email;
string firstname = me.first_name;
string lastname = me.last_name;
string birthday = me.birthday;
TextBox1.Text = email;
Everything seems to be generating correctly. Even after getting the wrong access token (which was a lot shorter than it is suppose to be) for about a week, I got it sorted. And now I am stuck.
I have also noticed in the C# sdk for Facebook you can create multiple instances for FacebookWebClient, FacebookApp, FacebookClient.
Which one do I use and could this be part of my problem?
There are utility classes in the Facebook SDK that deal with the access token for you. They were a little flaky when I looked at them a few weeks ago though.
I ended up using the javascript code instead - http://www.patternwebsolutions.com/2011/03/07/facebooksdk-connect-mvc3/

Categories