What is this code means? - asp.net

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)

Related

Mockito: HttpServeletRequest return mock Cookie not working as expected

I have a method hello(HttpServletRequest request) that needs to be unit tested. In this method, I do something like this Cookie cookie = WebUtils.getCookie(request, cookie_name). So basically, I extract the cookie here and do my stuff. This is how my test class looks like:
#Test
public void testHello() {
Cookie cookie = new Cookie(cookie_name, "");
Mockito.when(request.getCookies()).thenReturn(new Cookie[]{cookie});
Mockito.when(WebUtils.getCookie(request, cookie_name)).thenReturn(cookie);
// call the hello(request) and do assert
}
So whenever I try to mock and return this cookie, I end up with something like this in my stack trace.
org.mockito.exceptions.misusing.WrongTypeOfReturnValue:
Cookie cannot be returned by getCookies()
getCookies() should return Cookie[]
***
If you're unsure why you're getting above error read on.
Due to the nature of the syntax above problem might occur because:
1. This exception *might* occur in wrongly written multi-threaded tests.
Please refer to Mockito FAQ on limitations of concurrency testing.
2. A spy is stubbed using when(spy.foo()).then() syntax. It is safer to stub spies -
- with doReturn|Throw() family of methods. More in javadocs for Mockito.spy() method.
Inside WebUtils.getCookie(), it basically does request.getCookies() and iterates the array to get the correct one. This WebUtils comes from Spring Web. As you can see I have returned some value for that as well. Still getting this error. Has anyone faced this issue? How can I workaround this?
Following up on #Ajinkya comment, I think this is what he wanted to express:
The getCookie method might looks something like this (I just used some version of it, so there might have been some changes in the version you are using)
public static Cookie getCookie(HttpServletRequest request, String name) {
Assert.notNull(request, "Request must not be null");
Cookie cookies[] = request.getCookies();
if (cookies != null) {
for (Cookie cookie : cookies) {
if (name.equals(cookie.getName())) {
return cookie;
}
}
}
return null;
}
Since you mocked your request you can control what getCookies() is returning.
To make this method working (without mocking it), you just would need to return a mock instead of a real Cookie from getCookies().
Cookie mockCookie = Mockito.mock(Cookie.class);
Mockito.when(mockCookie.getName()).thenReturn(cookie_name);
Mockito.when(request.getCookies()).thenReturn(new Cookie[]{mockCookie});
Changing it to this and the static method can do its work as usual. You wouldn't need bother mocking it.

Show a message after redirecting after a successful POST request without using TempData

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"].
}

Is it thread-safe to write this?

Can I write something like the following (in an assembly being used in an ASP.NET web page)?
public static string CurrentAuthenticatedUserFromHttpRequest
{
get
{
if (HttpContext.Current.Items["AuthUser"] == null)
{
return string.Empty;
}
return HttpContext.Current.Items["AuthUser"].ToString(); //set in "TryAuthenticate"
}
}
It is going to be a static read-only property. The value (to HttpContext.Current.Items["AuthUser"]) is set through a httphandler.
Just wondering on how this would perform during multiple requests. Is the data going to be accurate when multiple users try to access the same property (in multiple requests), even when high volumes of requests come in?
Yes, this is threadsafe. The static HttpContext.Current property differs per thread and contains the context for the request that the thread is currently handling.

storing user ID in session

When the user logs in, I want to store his userID in the session with
HttpContext.Current.Session["UserID"] = 2354; (this is just a hard-coded example)
Then, when I run a page method, if I do
var test = HttpContext.Current.Session["UserID"];
will the variable test hold the value I stored when he logged in?
If this is a correct way of doing it, how do I access the session when I receive a call from a page method? I want to put the test =... line in a page method to identify which user the request is coming from.
Thanks.
As has been already answered, yes - it should be fine, though if you sit on a page too long before calling a service using this method [WebMethod] it will fail. Best practice in that case is to check for the session and rebuild as necessary. The same is true for any other authentication to ensure that they haven't become unsyncronized or expired.
[WebMethod(EnableSession = true)]
HttpContext context = HttpContext.Current;
if (context.Session["UserID"] == null) {
Utilites.PopulateSessionVars(context.Request.ClientCertificate, context.Request.ServerVariables["REMOTE_ADDR"]);
}
String userId = context.Session["UserID"].ToString();
(where Utilities.PopulateSessionVars is a method to rebuild the session data off of whatever you're using to log in ... which in my case is a PKI certificate)
Yes, that should work. However, session and forms authentication timeouts are on different timers and have different default timeouts so you cannot guarantee that value in session will be available for the time period during which the user is authenticated if you are using forms authentication.
This should do it
//Note: this code hasn't been tested. Correct me if I'm wrong
//To Set:
if (Session["UserId"] == null)
Session["UserId"] = "12345";
//To Get it:
if (Session["UserId"] != null)
MyObject.Id = Session["UsedId"].ToString();
Yes, but its advisable to do a test straight after your test variable assignment to make sure that the UserID was set correctly before you try to use it.
EDIT
You could try:
var test;
if (HttpContext.Current.Session["UserID"] != null)
{
test = HttpContext.Current.Session["UserID"];
}
Global.asax runs at the application level. You want the user sessions which is a differet http context. Initialize the Session in the home/default login page instead.

OpenRasta unit testing

I’m about to start work on an OpenRasta project (an xml over http web service). OpenRasta looks great but unfortunately worked examples seem few and far between on the internet. Looking at the test side of the project, if my handlers are returning strongly typed objects (not OperationResult), i.e.:
public class PersonHandler
...
public Person Get(int id)
{
...
How can I test for http status codes? (For example if the handler throws an uncaught exception). I’m not sure what level the tests pitch in at, and what needs mocking (using moq btw)
Any help appreciated, particularly coded examples!
I faced the same problem, and ended up writing my tests as integration tests at a much higher level, actually making real REST/HTTP calls through a simple HttpWebRequest client. This allowed me to check the HTTP response headers / status codes and double-check the JSON/XML serialization from the client's perspective, which was just as important as whether or not the operations succeeded.
I started by returning OperationResult from all my handlers, and used these to wrap the strongly-typed objects. My handlers all inherit from a base class with a few helper methods that make it easier to return a custom error with a user-friendly error message. The more I coded this up, the more my handlers resembled a ASP.NET MVC controller. e.g.:
public OperationResult GetById(int id)
{
try
{
// do stuff here
return OKResult( // some strongly-typed resource );
}
catch(SomeException ex)
{
return BadRequestResult(SomeErrorCode, ex.Message);
}
}
Then in the test client, it's pretty easy to just check the HTTP status code. Obviously this doesn't help much with mocking. I'm not sure what the best solution is, in fact I've favorited this question in the hope that someone answers it better than I can - but this has worked pretty well for me so far.
The handler is just a class--ideally with minimal dependencies--so your unit tests can just test the isolated logic in the class.
If you want to test for status codes, I recommend (based on very little experience!) using OpenRasta self-hosting.
Here's a test (somewhat changed) that I wrote recently:
[TestMethod]
public void POST_with_inaccurate_contentLength_returns_405()
{
var resource = GetResource();
IRequest request = new InMemoryRequest
{
HttpMethod = "POST",
Uri = new Uri("http://localhost/Resource"),
};
request.Headers.ContentLength = 16; //wrong!
request.Entity.Stream.Write(resource.Content, 0, resource.Content.Length);
var response = _host.ProcessRequest(request);
Assert.AreEqual(405, response.StatusCode);
}
I should add that the host is set up in the TestInitialize method as such:
_host = new InMemoryHost(new Configuration());
_host.Resolver.AddDependencyInstance(typeof(IFileResourceRepository), _repository, DependencyLifetime.Singleton);
...and is cleaned up in the TestCleanup method.

Resources