1)When exactly we need to use HTTPContext (exclusively), please elaborate with an example if possible.
2)What does the following code do
internal string QueryString( string name )
{
if ( HttpContext.Current.Request.QueryString[name] == null )
return string.Empty;
else {
return HttpContext.Current.Request.QueryString[name].ToString();
}
3)Is there any other alternative way where we avoid using HttpContext
Q1:
HttpContext is an object which encapsulates all HTTP-specific information about an individual HTTP request. So, if you need to get any information about receiving HTTP request (for example in order to get the query string parameter values, referral urls, User's IP address etc), you need to use HttpContext object. Further more, this object contains information of current Request, Response, Server, Session, Cache, User and etc.
More information
Usage and examples
Get current session Id: HttpContext.Session.SessionID
Get Timestamp of current request: HttpContext.Timestamp.ToString()
Q2:
In your code sample, you are trying get the value of query string parameter 'name'.
Your dummy request Url looks like - http://www.yourdomain.com/something?name=queryStringValue
QueryString parameter = name
QueryString parameter value = queryStringValue
Hope this helps.
Related
I am using the Post-Redirect-Get pattern.
In my asp.net core MVC web app, this is what happens:
User submits a form via POST which adds an item to db.
Controller adds the new item and redirects with 302/303 to "/Home/Index/xxxx", where xxxx is the id of the item.
The new request (/Home/Index/xxxx) is served by the controller, and it displays the item. And the item url in the address bar is something the user can copy and share.
At step 3 above, I would like to show the user a message saying "Item was successfully added".
This is my code (without the success message):
public async Task<IActionResult> Index(string id)
{
ItemView itemView = null;
if (string.IsNullOrEmpty(id))
itemView = new ItemView(); // Create an empty item.
else
itemView = await itemService.GetItemAsync(id);
return View(itemView);
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Index(ItemView itemView)
{
string id = await itemService.AddItemAsync(itemView);
return RedirectToAction("Index", "Home", new { id = id });
}
There are few ways to do this that I found in other answers on stackoverflow.
Redirect to "/Home/Index/xxxx?success=true". When action sees a success=true param, it can display the success message. But I don't want to use an extra param because I would like users to be able to just copy the url from the address bar and share it. And I don't want them sharing the url that has success param, because then everyone who clicks on the shared link will see the message "Item was successfully added".
This post suggests using TempData, which is a good solution. I think that would need me to enable sticky behavior on the server, which I would like to avoid if possible.
I can probably use referrer url to determine if the request came after a form submission, and in that case I can show the message.
The original answer by "snoopy" did point me in the right direction. But for some unknown reason, that answer no longer exists, so I am posting the answer myself in the hope it would benefit someone in future.
ASP .NET Core 1.1 and higher supports Cookie based Tempdata provider called CookieTempDataProvider. Link to Microsoft Docs.
This is similar to Session based Tempdata, but no data is stored on the server side. The response from the server set's a cookie in the browser with the data you want to store. The next request from the browser will include this cookie. The framework automatically parses this and populates this in TempData, which the controller can use. Once the controller reads this data, then the CookieTempDataProvider automatically adds the appropriate headers in the response to clear this cookie.
In your Startup class's ConfigureServices method, you need to register CookieTempDataProvider:
services.AddSingleton<ITempDataProvider, CookieTempDataProvider>();
To store some data in cookie based temp data, you simple set the value like this in your controller:
TempData["key"] = "value";
To read the data in your controller, you read it like this:
string value = TempData["key"];
if (value != null)
{
// Do something with the the value.
}
The check for non-null tells you if that key exists in TempData or not. Note that you can also check using .ContainsKey() method, but that is not counted as a read. The data (& the cookie) will not be cleared unless you read it. For example this will not clear the data:
if (TempData.ContainsKey("key"))
{
// Do something without actually reading the value of TempData["key"].
}
I have a class which is used to perform Validation of Antiforgery tokens where the payload is Json. That class looks like this (from Phil Haacked):
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = false, Inherited = true)]
public class ValidateJsonAntiForgeryTokenAttribute : FilterAttribute, IAuthorizationFilter
{
public void OnAuthorization(AuthorizationContext filterContext)
{
if (ReferenceEquals(filterContext, null)) throw new ArgumentNullException("filterContext");
var request = filterContext.HttpContext.Request;
// Only validate POSTs
if (request.HttpMethod == WebRequestMethods.Http.Post)
{
// Ajax POSTs and normal form posts have to be treated differently when it comes
// to validating the AntiForgeryToken
if (request.IsAjaxRequest())
{
var antiForgeryCookie = request.Cookies[AntiForgeryConfig.CookieName];
var cookieValue = ReferenceEquals(antiForgeryCookie, null) ? null : antiForgeryCookie.Value;
AntiForgery.Validate(cookieValue, request.Headers[AntiForgeryConfig.CookieName]);
}
else
{
new ValidateAntiForgeryTokenAttribute().OnAuthorization(filterContext);
}
}
}
}
This is the first Angular project I am using it on and it is not throwing an exception where I would expect it to. For example, the value in the header differs from the value in the cookie and the call to AntiForgery.Validate proceeds without exception.
The anti-forgery token is rendered in the shell view (i.e. Index.cshtml) and it is added to the headers in Angular's module run function:
// Handle routing errors and success events
theApp.run(['$http', '$route', '$rootScope', '$q', 'routeOverlord',
function ($http, $route, $rootScope, $q, routeOverlord) {
// Include $route to kick start the router.
routeOverlord.setRoutingHandlers();
// Include AntiForgeryToken to prevent CSRF attacks
$http.defaults.headers.common['__RequestVerificationToken'] = angular.element('input[name="__RequestVerificationToken"]').val();
}]);
Is this a known thing? Happy to provide a Fiddler screenshot of the differing strings in the cookie and header if requested.
Cheers
The cookie token and the form token (the one in the headers in your case) are not supposed to be identical (it would be easier to fake).
The cookie token contains a random blob. The form token contains the same blob, plus some identity data (and optionally some additional data).
AntiForgery.Validate() checks that both blobs are identical, and that the other data in the form token corresponds to the identity data and the optional additional data.
I have seen this as well. The cookie value and the field value being different but the .Net framework still letting them through.
This is because the .Net Framework's implementation is a little more complicated then a simple value matching check.
After looking over the source code on Github, see that the tokens contain additional information besides just a GUID (they are tying it to the current user).
I can see form the TokenValidator that the cookie value is a token representing a SessionToken where the field value (your header value) is not expected to be a session token.
// Do the tokens have the correct format?
if (!sessionToken.IsSessionToken || fieldToken.IsSessionToken)
{
throw HttpAntiForgeryException.CreateTokensSwappedException(_config.CookieName, _config.FormFieldName);
}
But the pair of them are still used to verify the action did come from the authorized user and not some precanned attack from a malicious person.
I personally need to do more studying of Microsoft's implementation, but from the little bit I see right now (and linked below) the values should most certainly be different.
References I looked at:
AntiXsrf AntiForgery
AntiXsrf AntiForgeryWorker
AntiXsrf TokenValidator
AntiXsrf AntiForgeryTokenSerializer
I have just employed in a company, this company have a web site, i see some code like this:
public TicketReader()
{
HttpContext currentReq = HttpContext.Current;
try
{
Ticket = ((FormsIdentity)currentReq.User.Identity).Ticket;
}
catch
{
Ticket = null;
}
}
what are these codes mean?
TicketReader is a method that saves the information involving the visitor's individual HTTP request in a variable called currentReq. That variable will be used to create a Ticket-object. If it fails the Ticket-object is set to be nothing, which will probably be checked later on.
More information on HttpContext class by MSDN.
the short answer is it looks at the current http request and sets a ticket to the user, if that throws an error it sets the ticket to null(instead of the error type the command probably returns)
I would learn about httprequests if I were you and it will start making sense
what it basically does it break hierarchy intentionally(useful yet dangerous if you don't understand what you are doing)
How do I pass a null value to an ASP.NET web service when accessing it via HTTP POST?
[WebMethod]
public string GetResult(DateTime date, int foo)
{
//do stuff here
}
When calling this method using HTTP POST, how do I pass a null parameter? Passing empty string just makes the server throw an exception trying to convert the string parameter to a DateTime. Making the DateTime parameter nullable (i.e. DateTime? date) seems to disallow calling it via HTTP.
Neither of these can have null values. They are both value types and can't be set to null even if you attempted to do it using code. I would recommend sending DateTime.MinValue and 0.
I am wondering how the HttpContext is maintained given that the request-response nature of the web is essentially stateless.
Is an identifier being for the HttpContext object being sent as part of the __EVENTTarget / __EVENTARGUMENTS hidden fields so that the HttpRuntime class can create the HttpContext class by reading this section from the request (HttpWorkerRequest)? I don't think
Please let me know as I am trying to fill some holes in my understanding of the http pipeline and I was unable to find any information about this.
I understand something like
HttpContext.Current.Session["myKey"] = Value;
just works but if I had to do something similar in a different language (say perl), I would have to use hidden fields for the same, wouldn't I?
Thanks
-Venu
The HttpContext is recreated for each request. The HttpSession, however, is stored on the server across requests. Basically, HttpSession is a Dictionary<string, Dictionary<string, object>>. The initial key, the session id, is provided by either a cookie or a query string parameter (if using cookie-less sessions). If you use Fiddler, you'll see the ASP.NET_SessionId cookie that contains the key for that user's session.
In code:
class HttpSessionState {
private static readonly Sessions =
new Dictionary<string, Dictionary<string, object>>();
public object this(string key) {
get {
return GetCurrentUserSession()[key]
}
set {
GetCurrentUserSession()[key] = value;
}
}
private Dictionary<string, object> GetCurrentUserSession() {
var id = GetCurrentUserSessionId[]
var d = Sessions[id];
if (d == null) {
d = new Dictionary<string, object>();
Sessions[id] = d;
}
return d;
}
private string GetCurrentUserSessionId() {
return HttpContext.Current.Request.Cookies["ASP.NET_SessionId"].Value;
}
}
The real implementation also handles session timeouts, abandons, and cookieless sessions - but the basic idea is the same.
I don't think there is one answer to your question, because I don't think everything under the HttpContext umbrella works the same way. In the example you chose, session state, both the key and value are stored on the server side. The way it knows how to hook up future requests to that session state is by using a cookie that has a (totally different) key in it. When the browser makes another request, it sends this cookie with the request and the server uses it to figure out which session to map to. Once it figures it out, you've again got access to your dictionary, across responses.
So, to do it in perl, you'd want to manually create a cookie and store a unique key in it, have a server-side mapping of those unique keys to session state dictionaries, and pretty much do what I described above.