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();
Related
I'm trying to create a user in Active Directory, using a function I adapted from some sample code I have found.
public bool crearUsuario(string usu, string pass, string path)
{
string path = #"LDAP://" + path;
//string oGUID = string.Empty;
try {
DirectoryEntry entrada = new DirectoryEntry(path);
DirectoryEntry nuevoUsuario = entrada.Children.Add("CN=" + usu, "users");
nuevoUsuario.Properties["samAccountName"].Value = usu;
nuevoUsuario.CommitChanges();
//oGUID = nuevoUsuario.Guid.ToString();
nuevoUsuario.Invoke("SetPassword", new object[] { pass });
nuevoUsuario.CommitChanges();
entrada.Close();
nuevoUsuario.Close();
return true;
}
catch (System.DirectoryServices.DirectoryServicesCOMException E)
{
//E.Message.ToString();
return false;
}
//return oGUID;
}
The original code returned a string (oGUID), but I only need a boolean.
My question is, why do they use that string? I only need true or false values, so I don't know if I need to return a string instead of a boolean value.
String seems an odd choice to me, also: I would have returned the raw Guid type. But the reason to return a string, guid, or other key, is there's an expectation you'll want to do something with that user account after you create it. Returning the new key as part of the original creation function is very likely to save you some work later.
If you know you won't be in that situation, it's perfectly fine to just return true/false... keeping in mind the comment on the question about letting the exception bubble up also has merit.
I am using c# and sitecore to basically use tokens in certain places ( see: how to create a custom token in sitecore ). I think I have a solution, but am not sure as to why it is not working, even though I am getting no errors.
Item tokenItem = Sitecore.Context.Database.Items["/sitecore/content/Site Content/Tokens"];
if (tokenItem.HasChildren)
{
var sValue = args.FieldValue.ToString();
foreach (Item child in tokenItem.Children)
{
if (child.Template.Name == "Token")
{
string home = child.Fields["Title"].Value;
string hContent = child.Fields["Content"].Value;
if (sValue.Contains(home))
{
home.Replace(home, hContent);
}
}
}
}
home and hContent pull up the correct values of each container, but when the page loads, it still has the "home" value inputted (the ie: ##sales) in the content area instead of the new value, which is stored in hContent. The sValue contains everything (tables, divs, text) and I was trying to single out a value that equals to "home" and replace the "home" value with hContent. What am I missing?
If your code is implemented as a processor for the RenderField pipeline, you need to put the result of your work back into args. Try something like this:
Item tokenItem = Sitecore.Context.Database.Items["/sitecore/content/Site Content/Tokens"];
if (tokenItem.HasChildren)
{
var sValue = args.Result.FirstPart;
foreach (Item child in tokenItem.Children){
if (child.Template.Name == "Token") {
string home = child.Fields["Title"].Value;
string hContent = child.Fields["Content"].Value;
if (sValue.Contains(home)) {
sValue = sValue.Replace(home, hContent);
}
}
}
args.Result.FirstPart = sValue;
}
Note that you need to be sure to patch this processor into the pipeline after the GetFieldValue processor. That processor is responsible for pulling the field value into args.Result.FirstPart.
You code isn't really doing anything. You seem to be replacing the tokens on the token item field itself (child.Fields["Title"] and child.Fields["Content"]), not on the output content stream.
Try the following, you need to set the args to the replaced value, replacing both the FirstPart and LastPart properties: Replace Tokens in Rich Text Fields Using the Sitecore ASP.NET CMS (link to the code in the "untested prototype" link).
I would refactor your code to make it easier:
public void Process(RenderFieldArgs args)
{
args.Result.FirstPart = this.Replace(args.Result.FirstPart);
args.Result.LastPart = this.Replace(args.Result.LastPart);
}
protected string Replace(string input)
{
Item tokenItem = Sitecore.Context.Database.Items["/sitecore/content/Site Content/Tokens"];
if (tokenItem.HasChildren)
{
foreach (Item child in tokenItem.Children)
{
if (child.Template.Name == "Token")
{
string home = child.Fields["Title"].Value;
string hContent = child.Fields["Content"].Value;
if (input.Contains(home))
{
return input.Replace(home, hContent);
}
}
}
}
return input;
}
This is still not optimal, but gets you closer.
Well, Do you know what happens when you performs home.Replace(home, hContent);, it will create a new instance by replacing the content of the come with what is in hContent so what you need to do is, assign this instance to a new variable or to home itself. hence the snippet will be like the following:
if (sValue.Contains(home))
{
home = home.Replace(home, hContent);
}
Have you tried:
home = home.Replace(home,hContent);
I cannot figure out how to fix this loop issue when i call a function like
new Common.Utility.Parameter().Get(Common.Constants.Parameter.SomeParameter);
Probably the error is caused by isHttpsCookie that recall the Parameter.Get()
Utility.cs
public static class Utility
{
public class Parameter
{
public string Get(string key)
{
string cookie = new Cookie().Read(key);
if (cookie == null)
{
var parameter = new Models.Parameter();
using (var db = new MyEntities())
parameter = db.Parameters.Where(w => w.Key == key).FirstOrDefault<Models.Parameter>();
if (parameter != null)
{
new Cookie().Write(key, parameter.Value);
return parameter.Value;
}
else
return string.Empty;
}
else
return cookie;
}
}
}
Cookie.cs
public class Cookie
{
private bool isHttpsCookie = Convert.ToBoolean(new Utility.Parameter().Get(Constants.Parameter.IsHttps)); // Loop here?
public string Read(string cookieName)
{
HttpCookie httpCookie = HttpContext.Current.Request.Cookies[HttpContext.Current.ApplicationInstance.GetType().BaseType.Assembly.GetName().Name + "_" + cookieName];
return httpCookie != null ? HttpContext.Current.Server.HtmlEncode(httpCookie.Value).Trim() : string.Empty;
}
public void Write(string cookieName, string cookieValue, bool isHttpCookie = true)
{
if (isHttpsCookie)
isHttpCookie = false;
var aCookie = new HttpCookie(HttpContext.Current.ApplicationInstance.GetType().BaseType.Assembly.GetName().Name + "_" + cookieName)
{Value = cookieValue, Expires = Common.Constants.Cookie.DefaultExpires, HttpOnly = isHttpCookie};
HttpContext.Current.Response.Cookies.Add(aCookie);
}
}
Apparently, your code is falling into a sort of recursion where you suspect it is. What I'm having trouble with is why are you creating new objects just to call a single method. Looks like you could have them as static methods in your classes, so no object creation would be needed, thus no 'looping'.
Have a closer look at your Cookie.Write() and Parameter.Get() method, they are calling each other. When you declare isHttpsCookie, you call Parameter.Get(). In the Parameter.Get(), if the condition is valid, it will call to Cookie.Write(). In its turn, when you call new Cookie(), the isHttpsCookie is called again and it's continuing forever.
Another point at this code:
if (isHttpsCookie)
isHttpCookie = false;
do you try to say that isHttpsCookie should be false at all time? so why do you need to declare this?
Solution: Do like #Takeshi said: those methods can be declared as static so no class declaration is required to called them.
You are correct in what you suspect. the isHttpsCookie declaration is causing you grief.
When the Cookie object is created it goes away and executes the method get from your utility class which creates an instance of cookie. Therefor you have your recursion.
You will need to change the way you initialise isHttpsCookie. Maybe only initialise / check if you are doing a write. After all you are most likely going to read more often than write.
Hope that helps.
I'm looking to see if there is a way to eliminate one of the two calls that gets made to my method to google maps to calculate long/lat coordinates.
Here is my method.
public static GeocoderCoordinates GetCoordinates(string region)
{
WebRequest request = WebRequest.Create("http://maps.googleapis.com/maps/api/geocode/xml?sensor=false&address=" + HttpUtility.UrlEncode(region));
using (WebResponse response = request.GetResponse())
{
using (Stream stream = response.GetResponseStream())
{
XDocument document = XDocument.Load(new StreamReader(stream));
XElement longitudeElement = document.Descendants("lng").FirstOrDefault();
XElement latitudeElement = document.Descendants("lat").FirstOrDefault();
if (longitudeElement != null && latitudeElement != null)
{
return new GeocoderCoordinates
{
Longitude = Double.Parse(longitudeElement.Value, CultureInfo.InvariantCulture),
Latitude = Double.Parse(latitudeElement.Value, CultureInfo.InvariantCulture)
};
}
}
}
return null;
}
The first time I call this method it's for validation.
internal class ValidateLocationAttribute : ValidationAttribute
{
public override bool IsValid(object value)
{
var location = value as string;
GeocoderCoordinates coordinates = Geocoding.GetCoordinates(location);
if (coordinates == null)
return false;
return true;
}
}
and if there is no location that gets found it returns null - validation fails.
The second time it gets called is in the controller to set longitude/latitude coordinates within my entity.
[HttpPost]
public ActionResult Edit(EditStudentViewModel viewModel)
{
if (ModelState.IsValid)
{
Student student = studentRepository.Find(User.Identity.GetUserId());
if (student == null)
{
var newStudent = new Student
{
AspNetUserRefId = viewModel.AspNetUserRefId,
CatchPhrase = viewModel.CatchPhrase,
StartedPracticing = Convert.ToInt16(viewModel.SelectedYearId),
LocationPoints = Geocoding.GetDbGeography(viewModel.Location),
Location = viewModel.Location,
SO I'm running through this method twice just to insert/update a student. It seems a little redundant.
Isn't there a way to trigger/set validation state while the code in the controller is running, so I don't have to call this method twice (once for validation and once to set the actual values) when the user submits the form?
I thought about caching but don't think it's a good idea, unless someone can point out something.
If you think applying validation upfront using an attribute on the text box serve value to the user (early feedback), keep things as it is. Two calls is not too bad at all considering the value and cleanliness of the solution.
Second option is you can remove the attribute, and perform the validation in the controller action. If validation fails, display same form with all the same data but error message for the text box value (location). User will need to choose another location and then submit.
It is a trade off.
Important Tip: You can optimize your solution by storing region names in your DB and going to google API only if the region name does not present in your DB.
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