I am trying to get the website id from IIS on Windows Server 2012 R2. I want to fetch the Id, then add a website pointer for the website in IIS. I'm not sure where to grant the permissions for the code to work and at the same time, not leaving my web server vulnerable.
Here is my code for fetching Id
string result = "-1";
DirectoryEntry w3svc = new DirectoryEntry(string.Format("IIS://{0}/w3svc", "localhost"));
foreach (DirectoryEntry site in w3svc.Children)
{
if (site.Properties["ServerComment"] != null)
{
if (site.Properties["ServerComment"].Value != null)
{
if (string.Compare(site.Properties["ServerComment"].Value.ToString(),
"website.com", true) == 0)
{
result = site.Name;
break;
}
}
}
}
return result;
This is the error that is thrown:
Access is denied.
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.Runtime.InteropServices.COMException: Access
is denied.
Source Error:
Line 22: DirectoryEntry w3svc = new
DirectoryEntry(string.Format("IIS://{0}/w3svc", serverName));
Line 23:
Line 24: foreach (DirectoryEntry site in w3svc.Children)
Line 25: {
Line 26: if (site.Properties["ServerComment"] != null)
Source File: c:\inetpub\wwwroot\DNS_IIS\DNS.aspx.cs Line: 24
Stack Trace:
[COMException (0x80070005): Access is denied.
]
System.DirectoryServices.DirectoryEntry.Bind(Boolean throwIfFail)
+597561
System.DirectoryServices.DirectoryEntry.Bind() +44
System.DirectoryServices.DirectoryEntry.get_IsContainer() +42
System.DirectoryServices.DirectoryEntries.GetEnumerator() +49
DNS.GetWebSiteId(String serverName, String websiteName) in c:\inetpub
\wwwroot\DNS_IIS\DNS.aspx.cs:24
DNS.btnDNS_Click(Object sender, EventArgs e) in c:\inetpub\wwwroot
\DNS_IIS\DNS.aspx.cs:85
System.Web.UI.WebControls.Button.RaisePostBackEvent(String
eventArgument) +155
System.Web.UI.Page.ProcessRequestMain(Boolean
includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
+3804
It was a simple thing to sort out.
So I just changed the Identity of the ApplicationPool to LocalSystem and it worked 100%.
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.
I published a LinkedIn article and I'm trying to retrieve the comments for this particular article. I obtained the articleId by right clicking on the comments button and copying the link address. I get aritcleId = 7434836657526032700. Should I use GET http://api.linkedin.com/v1/posts/{post-id}/comments where {post-id} is same as articleId?
Below is my code after successful AuthorizationLinkGet call.
string oauth_token = Request.QueryString["oauth_token"];
string oauth_verifier = Request.QueryString["oauth_verifier"];
if (oauth_token != null && oauth_verifier != null)
{
Application["oauth_token"] = oauth_token;
Application["oauth_verifier"] = oauth_verifier;
//get access token
_oauth.Token = oauth_token;
_oauth.TokenSecret = Application["reuqestTokenSecret"].ToString();
_oauth.Verifier = oauth_verifier;
_oauth.AccessTokenGet(oauth_token);
sLinkedInCommentsURL = "http://api.linkedin.com/v1/posts/7434836657526032700/comments";
string response = _oauth.APIWebRequest("GET", sLinkedInCommentsURL, null);
lblMessage.Text = response;
}
I receive following error:
Server Error in '/dreamplaybook' Application.
The remote server returned an error: (403) Forbidden.
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.Net.WebException: The remote server returned an error: (403) Forbidden.
Source Error:
Line 433: finally
Line 434: {
Line 435: webRequest.GetResponse().GetResponseStream().Close();
Line 436: responseReader.Close();
Line 437: responseReader = null;
Source File: c:\inetpub\calendias\dreamplaybook\App_Code\oAuthLinkedIn.cs Line: 435
Stack Trace:
[WebException: The remote server returned an error: (403) Forbidden.]
System.Net.HttpWebRequest.GetResponse() +6538872
oAuthLinkedIn.WebResponseGet(HttpWebRequest webRequest) in c:\inetpub\calendias\dreamplaybook\App_Code\oAuthLinkedIn.cs:435
oAuthLinkedIn.APIWebRequest(String method, String url, String postData) in c:\inetpub\calendias\dreamplaybook\App_Code\oAuthLinkedIn.cs:357
adposter.Page_Load(Object sender, EventArgs e) in c:\inetpub\calendias\dreamplaybook\adposter.aspx.cs:282
System.Web.Util.CalliEventHandlerDelegateProxy.Callback(Object sender, EventArgs e) +51
System.Web.UI.Control.OnLoad(EventArgs e) +92
System.Web.UI.Control.LoadRecursive() +54
System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +772
Version Information: Microsoft .NET Framework Version:4.0.30319; ASP.NET Version:4.0.30319.34237
Article ID is not the same field as post id, so that is why you are getting the error you see. The API does not allow you to get comments from publications.
I cannot seem to find out why my SQL data connections are not being recognized and the SQL Data Reader is not being able to read data when I publish my ASP.Net Site. It works when I just use the localhost and it is not published but once I publish it to IIS 7 it can no longer read data from SQL server. Please anyone if you can help that would great. I am very new to IIS 7 and cannot figure this out for the life of me. I have tried to check other blogs but I am coming up with nothing. The error that I am getting is:
Invalid attempt to read when no data is present.
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.InvalidOperationException: Invalid attempt to read when no data is present.
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:
[InvalidOperationException: Invalid attempt to read when no data is present.]
System.Data.SqlClient.SqlDataReader.CheckDataIsReady(Int32 columnIndex, Boolean allowPartiallyReadColumn, Boolean permitAsync, String methodName) +5327847
System.Data.SqlClient.SqlDataReader.TryReadColumn(Int32 i, Boolean setTimeout, Boolean allowPartiallyReadColumn) +47
System.Data.SqlClient.SqlDataReader.GetValueInternal(Int32 i) +31
System.Data.SqlClient.SqlDataReader.GetValue(Int32 i) +73
System.Data.SqlClient.SqlDataReader.get_Item(String name) +27
GLIncidentRequestForm._Default.Page_Load(Object sender, EventArgs e) +318
System.Web.Util.CalliEventHandlerDelegateProxy.Callback(Object sender, EventArgs e) +51
System.Web.UI.Control.OnLoad(EventArgs e) +92
System.Web.UI.Control.LoadRecursive() +54
System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +772
web.config connection string:
Page Code:
string connString = ConfigurationManager.ConnectionStrings["NPXL_REPORTINGConnectionString"].ConnectionString;
string strAccount = HttpContext.Current.User.Identity.Name.ToString();
string strUserName = strAccount.Split('\\').Last();
txtStrName.Text = strUserName;
string selectSQL = "SELECT sAMAccountName, mail FROM ActiveDirectories WHERE mail Is Not Null and sAMAccountName = '" + txtStrName.Text + "'";
SqlConnection con = new SqlConnection(connString);
SqlCommand cmd = new SqlCommand(selectSQL, con);
SqlDataReader reader = default(SqlDataReader);
try
{
con.Open();
reader = cmd.ExecuteReader();
reader.Read();
txtADName.Text = reader["sAMAccountName"].ToString();
txtEmail.Text = reader["mail"].ToString();
}
finally
{
reader.Close();
con.Close();
}
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/