help with NullReference exception in C# - c#

The following is a web method that is called from ajax, I have verified with firebug that the script is indeed passing two string values to my method:
public string DealerLogin_Click(string name, string pass)
{
string g="adf";
if (name == "w" && pass == "w")
{
HttpContext.Current.Session["public"] = "pub";
g= "window.location = '/secure/Default.aspx'";
}
return g;
}
I'm passing "w" just for testing purposes. If I delete the if block then I don't get an error back from the server. I'm confused.

Without seeing the stack trace, I would guess that HttpContext.Current or HttpContext.Current.Session is null.

Jeff is correct, but I wanted to add that using session within a web service requires that session be turned "on":
[WebMethod(EnableSession=true)]
public string DealerLogin_Click(string name, string pass)
{
string g="";
if (name == "w" && pass == "w")
{
Session["Public"]="pub";
g= "window.location = '/secure/Default.aspx'";
}
return g;
}

Related

`CallerArgumentExpression` is always null (C# 10)

I'm trying to use the CallerArgumentExpression attribute, in conjunction with the suggestion for validating records found here, but the expression is always null. I am doing this in a .NET6 Core console application. The exact same code works fine in LinqPad 7 (.NET6).
I have a base record that contains common validation methods (pretty much copied from that other answer)...
public record CommonValidation {
internal static bool NonEmptyOrNullString(string s, [CallerArgumentExpression("s")] string expr = default) {
if (string.IsNullOrWhiteSpace(s)) {
throw new ArgumentException($"{expr} cannot be null or empty");
}
return true;
}
internal static bool NonZeroInt(int n, [CallerArgumentExpression("n")] string expr = default) {
if (n < 0) {
throw new ArgumentException($"{expr} cannot be negative");
}
return true;
}
}
I can then create a record as follows...
public record Address(string Street, string City, string State, string Country, string Postcode) : CommonValidation {
private bool _ = NonEmptyOrNullString(Street)
&& NonEmptyOrNullString(City)
&& NonEmptyOrNullString(State)
&& NonEmptyOrNullString(Country)
&& NonEmptyOrNullString(Postcode);
}
If I try to create an Address with an empty State...
Address a = new("5 My Street", "Somewhere", "", "Oz", "12345");
...then the exception is thrown, but the expr variable is null. As I said, the exact same code works fine in LinqPad, even though both are using the same version of .NET/C#.
Anyone able to explain what's going wrong in the console app? Thanks
Visual Studio 2019 doesn't support C# 10. Make sure you're using Visual Studio 2022. LinqPad 7 does which is why it works there.

Filter out or overload method

I have a dilemma that I need help with. The method TAXCheckControlNumberForAccuracy goes into the database and does a Select * statement using the passed in variables.
However, each time the program runs any one of these variables could be null. All could be null. None could be null. (i'm using OCR to get the variables..so it is not always accurate)
Can someone give me some insight on the best way to solve this problem.
if ((City != null) && (Zip != null) && (State != null) && (Owner != null))
{
if (City.Length > 4)
{
ControlNumberMatch = TAXCheckControlNumberForAccuracy(Owner, Zip, State, City);
}
}
you can use a method with optional parameters. Like
public void TAXCheckControlNumberForAccuracy(string Owner = "default",
string Zip = "default",string State = "default",string City = "default");
Regardless of what you do, you still need to check each parameter individually. Create a method that does such.
void string CorrectParam(string param)
{
if (param == null)
return "default";
return param;
}
void TAXCheckControlNumberForAccuracy(string City, string Zip, string State, string Owner)
{
}
//call using this
TAXCheckControlNumberForAccuracy(CorrectParam(City), CorrectParam(Zip), CorrectParam(State), CorrectParam(Owner));

How to check if cookies are empty or not

I need to check if cookie is present with value or not. But I wonder if there is some quick and good way of doing so since if I need to check 3 cookies it seems bad to check with if or try.
Why it does not assign empty string to my variable if cookie is not present? Instead it shows Object reference not set to an instance of an object.
My code (it works, but it seems too big for this task, I think there should be a better way of doing this)
// First I need to asign empty variables and I don't like this
string randomHash = string.Empty;
string browserHash = string.Empty;
int userID = 0;
// Second I need to add this huge block of try/catch just to get cookies
// It's fine since I need all three values in this example so if one fails all fails
try
{
randomHash = Convert.ToString(Request.Cookies["randomHash"].Value);
browserHash = Convert.ToString(Request.Cookies["browserHash"].Value);
userID = Convert.ToInt32(Request.Cookies["userID"].Value);
}
catch
{
// And of course there is nothing to catch here
}
As you can see I have this huge block just to get cookies. What I would like is something like this:
// Gives value on success, null on cookie that is not found
string randomHash = Convert.ToString(Request.Cookies["randomHash"].Value);
string browserHash = Convert.ToString(Request.Cookies["browserHash"].Value);
int userID = Convert.ToInt32(Request.Cookies["userID"].Value);
Edit
Maybe I can somehow override the .Value method to my liking?
Just check if the cookie is null:
if(Request.Cookies["randomHash"] != null)
{
//do something
}
NOTE: The "Better" way of doing this is to write good code that is both readable and reliable. It doesn't assign empty string because this is not how C# works, you are trying to call the Value property on a null object (HttpCookie) - you cannot use null objects because there is nothing to use.
Converting to an int you still need to avoid parse errors, but you can use this built in method:
int.TryParse(cookieString, out userID);
which brings on another point? Why are you storing the userID in a cookie? this can be changed by the end user - I don't know how you plan on using this but would I be right to assume this is a big security hole?
or with a little helper function:
public string GetCookieValueOrDefault(string cookieName)
{
HttpCookie cookie = Request.Cookies[cookieName];
if(cookie == null)
{
return "";
}
return cookie.Value;
}
then...
string randomHash = GetCookieValueOrDefault("randomHash");
Or with an Extension method:
public static string GetValueOrDefault(this HttpCookie cookie)
{
if(cookie == null)
{
return "";
}
return cookie.Value;
}
then...
string randomHash = Request.Cookies["randomHash"].GetValueOrDefault();

Url.Host in HttpContext.Current.Request and Page.Request

I have following method:
public static string GetHttpHost(System.Web.HttpRequest hr)
{
return "http://" + hr.Url.Host + ":" + hr.Url.Port.ToString() ;
}
When I call this method with GetHttpHost(this.Request) and GetHttpHost(HttpContext.Current.Request), it returns different results.
For example:
My request page is http://192.168.1.103/mypage.aspx
In mypage.aspx.cs, calling GetHttpHost(this.Request) returns http://192.168.1.103:80
When rendering mypage.aspx, some biz logic is involved, so BLL.dll is loaded. In BLL.dll, calling GetHttpHost(HttpContext.Current.Request) returns http://app133:80 (app133 is our web server's name)
I searched in Stack Overflow, all related questions tell me that HttpContext.Current.Request and Page.Request are same object.
So, can anyone tell me what happened in my code?
Thanks.
No, HttpContext.Current.Request and Page.Request are not the same. Both are instances of the same class (HttpRequest) but those are different instances.
In each case, the private HttpRequest instance is created differently - I could not find the exact code creating it but keep in mind that HttpContext.Current is created only once, long before any Page.
It all boils down to the following code in HttpRequest class:
public Uri Url
{
get
{
if (this._url == null && this._wr != null)
{
string text = this.QueryStringText;
if (!string.IsNullOrEmpty(text))
{
text = "?" + HttpUtility.CollapsePercentUFromStringInternal(text, this.QueryStringEncoding);
}
if (AppSettings.UseHostHeaderForRequestUrl)
{
string knownRequestHeader = this._wr.GetKnownRequestHeader(28);
try
{
if (!string.IsNullOrEmpty(knownRequestHeader))
{
this._url = new Uri(string.Concat(new string[]
{
this._wr.GetProtocol(),
"://",
knownRequestHeader,
this.Path,
text
}));
}
}
catch (UriFormatException)
{
}
}
if (this._url == null)
{
string text2 = this._wr.GetServerName();
if (text2.IndexOf(':') >= 0 && text2[0] != '[')
{
text2 = "[" + text2 + "]";
}
this._url = new Uri(string.Concat(new string[]
{
this._wr.GetProtocol(),
"://",
text2,
":",
this._wr.GetLocalPortAsString(),
this.Path,
text
}));
}
}
return this._url;
}
}
As you can see, it first tries to read known request header (GetKnownRequestHeader method in System.Web.HttpWorkerRequest base class) and only if it fails it will invoke GetServerName method which will return either IP address or server name depending where the web application is hosted.
Didn't find any official documentation or proof as to why exactly one returns IP and other the machine name, but the above can explain the difference.

Not all paths return a value. - Optional return?

I am getting the error "Not all paths return a value", and I totally understand why.
As you can see I want to redirect the person isn't logged in, and obviously there is no return view.
I'm sure I'm going about this incorrectly. How should I be trying to do this?
public ActionResult Confirmation (Order Order) {
if (Session["CompanyID"] == null)
{
string url = Request.Url.Host;
if (Request.Url.Port != null)
{
url = url + Request.Url.Port;
}
url = url + "/signin.asp";
Response.Redirect(url);
}
else
{
int userID = (int)Session["CompanyID"];
Corp_User User = Repository.CorpUserDetails(userID);
return View(new OrderLocation { Order = Order, Location = WhygoRepository.RoomDetails(Order.roomId).First(), Corp_User = User });
}
}
Please note that I need to redirect to a classic ASP page, not an MVC action..
You must return a ActionResult. Use "RedirectToAction".
public ActionResult Confirmation(Order Order)
{
if (Session["CompanyID"] == null)
{
string url = Request.Url.Host;
if (Request.Url.Port != null)
{
url = url + Request.Url.Port;
}
url = url + "/signin.asp";
return RedirectToAction(<YOUR ACTION>);
}
else
{
int userID = (int)Session["CompanyID"];
Corp_User User = Repository.CorpUserDetails(userID);
return View(new OrderLocation { Order = Order, Location = WhygoRepository.RoomDetails(Order.roomId).First(), Corp_User = User });
}
}
You could return a RedirectResult - http://msdn.microsoft.com/en-us/library/system.web.mvc.redirectresult.aspx
Well, this is a good question actually. See dknaack's answer for a solution in your particular case however in other circumstances we might not be so lucky.
Technically this situation is very logical. Redirect just opens up a new request and either lets the current request handle itself nicely or forcefully close itself. In all cases the current method needs a return value. If Redirect lets the current process handle itself nicely meaning you should have a return value that makes sense.
I think one solution would be to throw a specific exception after the redirect. Something like:
public string GetCurrentUserName()
{
if (!authenticated)
{
Response.Redirect(LoginScreen);
throw new UnresolvedMethodException();
}
else
{
return UserName;
}
}
Returning NULL is an option i wouldnt put my money on since NULL might also mean that there is no UserName Set (in the above case, a user might login using his email making the username optional).
Just put return null; under Response.Redirect(url); It will never actually reach that position, but it will get rid of the compiler error.
You could return null and check for that.
edit: I was way to quick, ignore me :P

Categories

Resources