C#.NET - How to check that Httprequest.form is invoked? - c#

I have a module that it is a middelware on owa and it must be add to IIS. It is work fine. But in some situation (on post request) I get this error:
This method or property is not supported after HttpRequest.Form, Files, InputStream, or BinaryRead has been invoked.
This is my code:
var context = HttpContext.Current;
var state = context.Request.Form["state"]; // error
I think this error when occure that my code should not read 'httprequest.form'.
My question is:
Is any way to I can know that httprequest.form should not is read.(Like a flag or ...)

The error message you're encountering occurs when you try to access the HttpRequest.Form property after it has already been read. This is because the HttpRequest.Form property is a one-time read-only collection, and once you access it, the data is consumed.
One way to check if the HttpRequest.Form property has already been read is to check the HttpRequest.HasForm property, which returns a Boolean indicating whether the form collection has been accessed.
Here's an example:
var context = HttpContext.Current;
if (context.Request.HasForm)
{
var state = context.Request.Form["state"];
}
By checking the HasForm property, you can avoid accessing the Form property if it has already been consumed.

Related

Is it possible to change the value returned by Server.GetLastError()?

I have written an HttpModule for ASP.NET which will inspect the current exception (if any) and wrap it in a new exception with a unique identifier. Then I want Elmah to log that wrapping exception.
My module is working and is sitting in front of the Elmah module, however I can't work out how to change the Server.GetLastError() so that my new exception will be logged!
I have tried:
var originalException = context.Server.GetLastError();
var app = (HttpApplication)sender;
var context = app.Context;
context.ClearError();
context.AddError(new WrapperException(originalException));
But doing so makes the context.Error property return null.
In fact ClearError doesn't do what it's advertised to do: "Clears all errors for the current HTTP request."
It doesn't do this. The AllErrors array still contains exceptions; all it does make GetLastError return null.
You cannot set context.AllErrors, nor poke something into the array (it's a copy).
You also cannot throw a new exception: the error page only sees the original exception, and Elmah doesn't even log it.
I'm beginning to think that it's not possible.
If the only reason you want to replace Server.GetLastError() is to make sure that ELMAH logs the right exceptions, there may be a better approach. ELMAH's filtering feature can be used to override the logged exception. To do so, add the following code to your Global.asax.cs file:
void ErrorLog_Filtering(object sender, ExceptionFilterEventArgs args)
{
var httpContext = args.Context as HttpContext;
ErrorLog.GetDefault(httpContext).Log(new Error(new WrapperException(args.Exception)));
args.Dismiss();
}
The ErrorLog_Filtering method is called by ELMAH just before logging any uncaught exceptions to the configured error log. In the example, I pull the information about the error happening (args.Context and args.Exception) and wrap the thrown exception in a new exception (WrapperException). By logging the new exception using the ErrorLog.GetDefault(...).Log(...) method, I make sure that ELMAH doesn't call the ErrorLog_Filtering method recursively (it would if you used ErrorSignal...Raise()). Finally, I dismiss the original exception, to avoid the error being logged twice.

Read patched attribute values from config files?

I want to read the patched attributes that are in Sitecore.ItemWebApi.config to determine whether the Sitecore Item API is enable in my site. This value I'm looking for is itemwebapi.mode, and I want to see whether it's set to 'Off' or not.
<site name="mysite">
<patch:attribute name="itemwebapi.mode">StandardSecurity</patch:attribute>
<patch:attribute name="itemwebapi.access">ReadOnly</patch:attribute>
<patch:attribute name="itemwebapi.allowanonymousaccess">false</patch:attribute>
</site>
I tried getting ConfigurationManager.AppSettings["itemwebapi.mode"] but it returns null. How do I get this value?
I think you need to use sitecore configuration factory to read the configuration stuff.
(http://sitecore-community.github.io/docs/documentation/Sitecore%20Fundamentals/Sitecore%20Configuration%20Factory/#config_factory)
Try as below. If not working experiment in similar way.
var refObj = Sitecore.Configuration.Factory.CreateObject("site/patch:attribute", true) as itemwebapi.mode;
If not useful, put a comment. I will delete it.
You can access the attributes on the site node using the Properties accessor,
if the attribute is not set then the value will be empty. For the current Context site:
string mode = Sitecore.Context.Site.Properties["itemwebapi.mode"];
string access = Sitecore.Context.Site.Properties["itemwebapi.access"];
string anon = Sitecore.Context.Site.Properties["itemwebapi.allowanonymousaccess"];
If you are checking within an ItemWebApi request (beginning with -/item/) then you can check the ItemWebApi.Context:
if (Sitecore.ItemWebApi.Context.Current != null)
{
Mode mode = Sitecore.ItemWebApi.Context.Current.Settings.Mode;
AccessType access = Sitecore.ItemWebApi.Context.Current.Settings.Access;
bool anon = Sitecore.ItemWebApi.Context.Current.Settings.AnonymousAcessAllowed;
}
This will give you strongly typed access to the settings using enums. Unfortunately the overloaded constructor for RuntimeSettings() is marked as internal so it is not possible to new this up yourself in a normal web request but could check the code and do something similar if you need.

Request.QueryString not recognized, System.Web included in namespace

A simple question but I'd rather ask since I had problem with it two times.
I am trying to retrieve hostname from the url in ASP.NET project. The code is actually not in a web page but in a class (part of the domain). System.Web is included in the headers. When I try to use Request.QueryString it is not recognized. Even worse if I try HttpContext.Current, I get this error
'System.Web.HttpContext.Current' is null
Here is my code
using System.Web;
public class MyNightlyJob : AbstractJob
{
public override void ExecuteJob(IJobExecutionContext context)
{
HttpContext.Current.Request.ServerVariables["HTTP_HOST"]; // does not work
Request.ServerVariables["HTTP_HOST"]; // this does not work also
}
}
What am I missing? Note that my question is actually about Request.ServerVariables but if one works, the other will work too.
Note that Request.ServerVariable is not recognized in the code at all. HttpContext.Current is recognized but I get run time error for that.
You need to check if HttpContext.Current is a null. If it is null then its not in the right context to be retrieved.
If you can modify the function, I would pass the HttpContext.Current as a variable or pass the host as a variable.

load child objects in EF5

I have a method in my generic repository:
public IQueryable<T> Query<T>() where T : class, IEntity
{
return _context.Set<T>();
}
This is method for getting user:
public User GetUser(string email)
{
return _repository.Query<User>().FirstOrDefault(u => u.Email == email);
}
Finally, I put the user to session:
AppSession.CurrentUser = UserService.GetUser(email);
In my action I need to get the current user and get collection of objects Notifications (one-to-many):
AppSession.CurrentUser.Notifications.OfType<EmailNotification>().FirstOrDefault();
But, here I get the error:
The ObjectContext instance has been disposed and can no longer be used for operations that require a connection.
I know that Notifications not loaded when I getting User from DB.
How to say EF to load Notifications objects? I know about Include, but I cannot use it in GetUser method.
When the first HttpRequest ends after looking up your CurrentUser object, your _repository reference that the CurrentUser is expecting for additional lookups like EmailNotifications isn't available.
The exception is thrown because CurrentUser doesn't have the original object context, so you either have to attach the CurrentUser object to the new objectContext that your _repository is using, or use the easier solution of simply reloading the user through the new context that was created for your current request in the repository.
Before attempting to find the notifications in your action, add the following line:
AppSession.CurrentUser = UserService.GetUser(AppSession.CurrentUser.Email);
AppSession.CurrentUser.Notifications.OfType<EmailNotification>().FirstOrDefault();
As #Ryan said it is due to the fact that the object context is not available to lazy load in the associated notifications.
What I'd suggest is turn off lazy loading (if possible) as can cause lots of issues later and then do something like ...
var user = UserService.GetUser(AppSession.CurrentUser.Email);
user.Notifications = NotificationService.GetUserNotifications(user.Id /* or another identifier */);
AppSession.CurrentUser = user;
To do this you will require a new NotificationService, this can load (as suggested above) but also handle the execution of notifications (sending emails etc).
You should now have the notifications for that user in your Application session cache.
HTH

Session State variables aren't working

I'm writing an ASP.NET C# web site that needs to access data from a database and show it to the user for viewing and editing. The specific data it accesses is based on the user who logs in, and I need for multiple users to be able to use the site simultaneously, viewing and editing different data as they do so. I stumbled upon the concept of Session States, and after a lot of reading and not as much understanding. I've come across a problem.
In my default page, I do this to create a Session variable:
Session.Add("UserData",userdata);
I have also tried this:
Session["UserData"] = userdata;
Then in a later page, I do this to try to call it:
object myobject = Session["UserData"];
This gives me an error, saying that Session["UserData"] is not set to an instance of an object. This is the method everyone seems to be using, is there something I'm missing?
My site is configured on IIS to have the Session State Mode set to "In Process", but most people seem to set this manually using their web.config file. However, when I try to do this in my web.config file I am always greeted with "unrecognized configuration section". My compiler doesn't know what this is:
<sessionstate mode="inproc"/>
EDIT, more detailed code:
MyClass userdata = new MyClass();
userdata.name = "myname";
userdata.number = 5;
Session["UserData"] = userdata;
later...
MyClass mydata = (MyClass)(Session["UserData"]);
This returns the error that Session["UserData"] is null.
The fact that you can't set the session mode in the web.config is a red flag to me of something weird and smelly going on. So ...
Check that the session mode is under the system.web element of the web.config otherwise it won't be valid.
Check that enableSessionState hasn't been set to false in either the web.config or the page directive
Try to rule out IIS. If possible convert your website to a web app and run through visual studio so it starts with it's own built in web server. What happens then? Is the Session state back?
It should n't make a difference but if you are not doing the test in Page_Load then just try it there - just in case you are doing these tests somewhere unusual.
Whatever the answer is to this when we know it will be headachingly obvious. I'm geninuely looking forward to finding out what it is. Good luck
Session variables are good to manage multiple users on your website, but to initialize them you should use the Global.asax file in your web application. This file has two methods specifically for Session variables, Session_Start and Session_End. To initialize your Session variable you would use code liked the following in Global.asax:
void Session_Start(object sender, EventArgs e)
{
// initialize session variable
Session["MySessionVar"] = 1;
}
Also you may have to cast the value of your session variable if you are doing operations on it like +, for example if you have a session variable holding an integer value, you may have to do like the following:
Session["MySessionVar"] = ((int) Session["MySessionVar]) + 1;
Also, if you try to use your session variable outside of a method like Page_Load or other method, like trying to use it as a property of the System.Web.UI.Page class in your C# code behind file, that may not work, you can only use your session variables within a method.
I would search for any calls to Session.Clear or Session.Abandon to see if your session is being purged in between those two actions.
You could also hook up to the Session_End event and see if that gets hit sometime in between the two calls.
Where you have
Session.Add("UserData",userdata);
you want to check the value you need to cast the object with (string) like this
string userdata= (string)(Session["UserData"]);
you could then run a check to see
if(string.IsNullOrEmpty(userdata))
but not sure how you are initializing and assigning a a value to userdata
Does it complain the your myobject is null or that Session is null? When you try to retrieve the value you are doing this from the method of what class?
Yet another question - by any chance are you trying to access it in a parallel thread?

Categories