SignalRv2 - Passing values to Hub - asp.net

Ill try my best to explain this. In my Hub code, i have instantiated the ConnectionMapping class. It was taken from here http://www.asp.net/signalr/overview/guide-to-the-api/mapping-users-to-connections#inmemory .
This ConnectionMapping requires a unique key for its dictionary. I have a webform code-behind called default.aspx.cs. In this code behind, I will get a unique Login Username inside the Page_Load event. How do i pass this username to the Hub to add it to the ConnectionMapping?
I tried.
IHubContext hubContext = GlobalHost.ConnectionManager.GetHubContext<MyHub>();
But i dont know what im doing after doing this. Help.

The short answer is, you don't. Not with the code you have. The issue is this sequence:
Client requests page
Server-side code runs (Page_Load)
Resulting HTML/JS is sent to client
Client connects to SignalR
At this point, you would presumably add to the ConnectionMapping. The issue being of course, that any data/variables in Page_Load are no longer available, and you'd have no way of mapping the connection you just received to that page request even if they were.
Your website needs to hold on to some piece of information, perhaps that username, and pass it to the hub on connection (possibly via the query string). The data could even be stored in the page as part of the Page_Load event (in a hidden div or through some other mechanism).
Now you have both pieces of information at the same time, and can add to the mapping normally.

Related

Can I ko.observable a session variable?

I have 2 simple aspx pages. On my default page, I have a simple label that's using ko.data-binding to a Session variable.
I thought if I change that variable KnockoutJS would update the user interface. When I click the button on sessionchanger page I changed the session variable that is being observed by ko. Where did I go wrong?
You have to change value of status property of viewModel instance to reflect changes on ui.
var vm = new viwModel;
ko.applyBindings(vm);
vm.status('new value');
You bind vm object to body not session object. You just use session object to initialize vm.status property.
So, you can't set new value in vm.status from the other page.
To be able to track it you should use client-server communication. It can be AJAX with polling functionality or WebSocket. So, you should check or listen server side and if any changes occur you can update vm.status property and after that it will reflect ui as you expect.
You cannot do it because asp.net rendering engine simply pass value of Session["target"] and not any link to that variable, also your knockout code isn't well written, see #Viktor Kukurba answer to get clearer idea of how to use and apply data-binding.
To achieve desired result you could use one of techniques listed below:
Preferable
Use WebSockets to notify your "Default" page about changing session variable by "Session Changer" page.
Take a look on tutorialBuilding real-time web apps with WebSockets using IIS, ASP.NET and WCF to get practical knowledge of how apply that techniques.
Workaround
As workaround you could get quite similar to required behaviour after applying next steps:
Create asp.net http request handler which would return value of Session["target"] in json format.
Create javascript function (let's call it refreshSessionTarger), which would send AJAX request to newly created asp.net http handler and update value of observable variable ( so knockout would reflect to that change, but note that you have to add ko data-binding properly).
Put refreshSessionTarger function created in step 2 into setInterval function as callback and set interval of how often in milliseconds refreshSessionTarger shall be executed.
function refreshSessionTarger(){
// perform ajax request and update variable which holds session target
};
var delay = 5000;
setInterval(refreshSessionTarger, delay)

how to disable reaching ajax call from browser

I have following ajax call
open: function () {
$(this).load("MyBox.aspx?sec=L&levId=" + RowId);
}
so people can see the querystring, so the user can copy url and paste it to browser but how can i block that? I dont want it to shown from browser. How I can do that? I m using asp.net and jquery.
load function issues a GET request. Instead of that, you may use a jQuery POST call and get the data. Users can't get the result by pasting it in browser and hit enter (which is GET request)
var thatObject=$(this);
$.post("MyBox.aspx?sec=L&levId=" + RowId,function(response){
thatObject.html(response);
})
In the server page, you can read the values posted by checking the Request.Form collection (instead of Request.QueryString).
from msdn
The Form collection retrieves the values of form elements posted to
the HTTP request body, with a form using the POST method.
You can determine whether the call is a GET call or POST call by inspecting the Request.RequestType property value. This way you can avoid people issuing GET request to this method and getting the response.
But remember that, there are tools/browser addons which does the POST request from browser.
Also if the data is for authorized users, you may check the user is authorized to access it in the server page(MYbox.aspx) before returning the content.
You can't. You can never trust any code running on the client. If you need to hide data on the client, you should create a server based session and then put a session token in an encrypted cookie.
From wikipedia and W3C
Some methods (for example, HEAD, GET, OPTIONS and TRACE) are defined as safe, which means they are intended only for information retrieval and should not change the state of the server. In other words, they should not have side effects, beyond relatively harmless effects such as logging, caching, the serving of banner advertisements or incrementing a web counter.
Making arbitrary GET requests without regard to the context of the application's state should therefore be considered safe.
By contrast, methods such as POST, PUT and DELETE are intended for actions that may cause side effect
If your get request changes the state of the server (which it most likely does based on your post), you are doing something wrong. What you're trying to do is impossible. You need to rethink your architecture.

ASP.NET Hidden Field Persistence During Life Cycle

I feel like I may be overlooking a fundamental concept of the page life-cycle here and have been (either because I can't figure out the right keywords or it hasn't been asked) unable to locate an existing answer so forgive me if this has been asked.
Basically, I need to persist a mutable object between the client side and the server side. Since the viewstate is encrypted/serialized and the session state is server-side only, my solution was to use a hidden field--easy enough, right? Well here's my problem... it seems as though it's working but the data isn't being propagated as I would've expected.
My expectation was this:
Page is loaded for the first time. Server-side class recognizes that the hidden field is empty, initializes the container class, serializes the class to a JSON string and writes that value to the hidden field.
Page_Init: Unavailable.
Page_Load: Unavailable.
Page_LoadComplete: Available.
Server processing completes, object is now available for use by client code.
Object in hidden field is mutated by client code. Client code then fires a postback to the server (via a button).
Server-side processing begins...
Page_Init: Unavailable.
Page_Load: Available, including client-side changes.
Page_LoadComplete: Available, including client-side changes.
All is right in the world, a double-rainbow shines outside my window and a magical unicorn gives me a wink and a nod.
My observation is this:
Page is loaded for the first time. Server-side class recognizes that the hidden field is empty, initializes the container class, serializes the class to a JSON string and writes that value to the hidden field.
Page_Init: Unavailable. (As expected)
Page_Load: Unavailable. (As expected)
Page_LoadComplete: Available. (As expected)
Server processing completes, object is now available for use by client code.
Object in hidden field is mutated by client code. Client code then fires a postback to the server (via a button).
Server-side processing begins...
Page_Init: Unavailable. (As expected)
Page_Load: Available, but not updated with changes made on the client-side. (Unexpected).
Page_LoadComplete: Available, including client-side changes. (As expected)
A dark cloud forms over my cubicle and I begin to contemplate whether or not my laptop would survive the second-story fall off the balcony.
Conclusion
This is causing me a bit of confusing for a couple reasons... the first is that I've never used the "LoadComplete" event before and can't seem to find any examples that suggest it's necessary to or even that it should be done that way. The second is that by the time load complete is raised, other events that rely on the data from the client side have already been fired.
Any help/explanation/suggestion; hell, even criticism is appreciated!
Thanks, Jason
I'm answering this in the hope that this helps save someone else a few hours. After much trial and finally success, I learned that you can get a HiddenField value during the OnInit event. Given a HiddenField with an ID of hidValue, the key line is:
string strValue = Request.Form[hidValue.UniqueID].ToString();
I've ripped a lot of hair on ASP.NET lifecycle :-). I would advise you this:
bind to control events
avoid binding or overriding to page
events
In this case, you should have a protected HiddenField declared in your page/user control. So you really want to bind to the ValueChanged event, and forget about the rest.
Explaination
You can update HiddenField values in javascript and get them back at the server.
If you want your object to be available after Load, using LoadComplete is ok.
If you want this object to be available to all controls when they load, the earliest you can get the data from inputs is by overloading PreLoad and creating your object there.
There is no problem with your logic.
Conclusion
There is some bug in your implementation of it.
Lets take a look at the code now.

Custom Elmah YSOD data

I'm using Elmah with ASP.NET and wondering how I would add custom data, such as a session variable, to an unhandled exception email.
I've tried several handlers in the Global.asax file but can't seem to find the right one.
For this, I'd think you would need to modify the Elmah source and recompile. It shouldn't be too difficult to achieve. If you have a look in the constructor of the Elmah.Error class, the HttpContext is passed in, from which you should be able to get the info you need, e.g. Session, Form variables etc. You could add custom fields to the Elmah.Error class for this data
I think the Elmah.ErrorMailHtmlFormatter class is where the email is constructed using a HtmlTextWriter, and here you could insert code in the RenderSummary() method to include the custom fields you added to Elmah.Error.
I know it may be a pain to start working with source, but personally I think it's the cleanest way as there currently is no facility for report/email templates, and it's better that bolting on something to change the output after it has been generated.
Andrew's answer helped a lot, thanks. I ended up doing the following:
Added a OnBuilding event to the ErrorMail http module. The event args for this event have a NameValueCollection property.
I handled the OnBuilding event in global.asax.
Since HttpModules don't always have access to sessionstate, esp. if the exception occurs before the session is loaded, I copied the data i wanted reported into the HttpApplication cache(indexed by sessionid).
When an exception occurs I grab the data i want out of the application cache via the sessionid stored in the request(specifically, in the cookie). I generate a NameValueCollection from this data and send it back to the httpmodule via the OnBuilding args.
The data is then rendered to email similarly to how the server variables section is rendered.

Post data with jQuery to ASP.net, am I doing this secure enough?

For a website I am building, I am using jQuery to post data to Generic Handlers I created for this purpose.
Because you need to be logged in, to do most post actions (like 'rate a picture'), I am currently using the following technique:
User visits page
Page determines if user is logged in
On Page_Load the page fills a hidden field with an encrypted string, which contains several needed variables, like User ID, Picture ID (of the picture they are currently viewing), the DateTime when the page was rendered.
When the user clicks a "I like this picture"-button, I do a $.ajax post to my Generic Handler, with the encrypted string and the value whether or not they liked the picture.
The Generic Handler decrypts the supplied encrypted string and takes a look at the DateTime to determine if it was not too long ago
When everything works out, the vote is submitted to the database.
In my understanding this is a pretty secure way to handle a situation like this. But maybe I am missing a very important point here.
Any advice would be very welcome.
Looks okay to me.
It looks like you're using a token pattern, a good method with which to secure stateless communications.
You should remember that $.ajax calls to your Handler will also support native ASP.NET security mechanism. When you perform $.ajax the .ASPXAUTH cookie is being add to cookies collection, so you can check in your Handler for this cookie, check HttpContext.User and limit access to the path of your handler in web.config - this all works.

Resources