Pass data from controller to controller safely - ruby-on-rails

I have 2 controllers: a Subscriptions controller and a PaypalExplress controller. First handles all subsription data, second handles paypal transactions.
The problem is a have to path somehow a price amount (#subscription.price) from Subscriptions to paypal controller. I thought about session[] and params[] hashes, but I assume it's not a secure way to do this.

Try this...
You can encrypt and decrypt your session parameter.
Encode(Session["price"].ToString());
public string Encode(string encodeMe)
{
byte[] encoded = System.Text.Encoding.UTF8.GetBytes(encodeMe);
return Convert.ToBase64String(encoded);
}
public static string Decode(string decodeMe)
{
byte[] encoded = Convert.FromBase64String(decodeMe);
return System.Text.Encoding.UTF8.GetString(encoded);
}

Is #subscription not an instanced model? If you have a row in a database just redirect to the appropriate URL passing along the subscription ID and retrieve the data on the other side.
You need to understand routing and it wouldn't hurt to read some getting started guides on the MVC principle.

Related

Encrypt data passed in View Model

I have a simple post method in a MVC controller that checks whether the ModelState is valid then calls another method passing an instance of the model as a paramter. This model contains sensitive data that is easily obtained by looking at Fiddler. My goal is to somehow mask or encrypt this data so that it cannot be seen in an http trace.
I have seen posts suggesting to use Session or Temp variables but that is not an option in my case.
This is what the code looks like:
[HttpPost]
[ActionName("Search")]
[AccessControl(Xri)]
public ActionResult SearchPost(string string1, ViewModel model)
{
model.NoResults = false;
if (ModelState.IsValid)
{
if (ModelState.IsValid) return RedirectToAction("TargetAction", model);
}
}
[AccessControl(Xri)]
public ActionResult TargetAction(string arg, ViewModel viewModel)
{
.
.
.
}
Fiddler shows the following:
/TargetAction?id=01010101&date=08%2F14%2F2013%2000%3A00%3A00&To=08%2F21%2F2013%2000%3A00%3A00&param1=somevalue&param2=somevalue2
Is there a way to mask the url parameters shown here?
You're going to need to get SSL running on your server.
Without a server certificate from a trusted authority, there is very little you can do to encrypt the data over the wire. Why? Because you'd need to send encryption/decryption details in clear text before you start sending the data so that your client (likely JavaScript) could decode it.
Using a certificate and operating on 443 gives you built-in functionality from the server/browser that is hard to beat in a custom implementation.
If you just want to obscure the data (and put it beyond the level of most web users) you could always base64 encode the data, rather than encrypting it. Just be clear that you are NOT encrypting data and it is still possible to decode it. This approach is not a form of encryption.
If you decide to take that approach regardless, here are a few resources:
Client-side Encoding/Decoding
MSDN Reference on Encoding to Base64
Cheers.
You have two options for doing this:
Store the data on the server and give the user a token (e.g. a GUID) to pass along to retrieve the data. Since using the Session or TempData is not an option, you could store the viewmodel in the database, and then redirect the user with the token in the URL to retrieve it on the next request.
The other option would be to have the user pass the viewmodel in the URL as you're currently doing, but pass it in an encrypted format. For example, you could
serialize the model to JSON, encrypt it using one of .NET's built in encryption algorithms, and then redirect to the next action passing the encrypted string as your view model. Then you could change the target action to something like:
[AccessControl(Xri)]
public ActionResult TargetAction(string arg, string encryptedViewModel)
{
var decryptedString = Decrypt(encryptedViewModel) ; // supply the decrypt function to match your encryption
var viewModel = JsonConvert.DeserializeObject(decryptedString);
}

ASP MVC4: A issue when manipulating variable value in controller

Thanks everyone's effort of helping me out, basically I'm facing a problem in controller below, just make it simple and easy:
Controller C{
public list<model> a;
//used in action A, if it's a searched list, then don't initialize;
public bool searched = false;
public ActionResult A(){
if(searched){
ViewBag.a = a;
}else
//initial the list
a = db.model.where();
.....
return view()
}
//return a result list when people search by keywords
public ActionResult B(string str){
a = db.model.where(d=> d.id = str);
search = true;
}
}
But, it turned out that the value of both a and researched never changed after B called
Did I miss some critical knowledge in .NET MVC?
Any related articles are very welcomed
Thanks
You should use TempData to keep your value after redirect. It is exactly TempData was designed for.
In your example it will be:
Controller C{
public ActionResult A(){
TempData["str"] = "this is A";
return RedirectToActionB()
}
public ActionResult B(){
TempData["str"] += "This is B";
return View()
}
}
I'm guessing you're asking because it's not giving the result you expect, rather than because you want someone to try it for you. The easy answer (assuming you meant "On the B's View Page") is "This is B".
A RedirectToAction will send a redirection to the browser, which initiates a new request to the server. Unfortunately a ViewBag's life is only for a single request, so it will no longer be populated when action B runs.
You will need to find another way to pass the data; for example, in a cookie or within the Session object.
Instead of:
return RedirectToActionB()
Try:
return B();
You'll save a redundant Http request as well.
In asp.net mvc controller doesn't keep it's fields/properties during requests: you'll have new instance of C on each web request. This means that you cannot expect a and searched fields to keep their state after action B completion.
You may use ViewBag(ViewData) to pass values between controller and view during request.
You may use TempData to store values during 2 requests, it's usually being used in PRG pattern for example.
You may use Session to keep your values while client's session is alive.
You may pass values between requests using hidden inputs on your page, query parameters, or less obvious things like HttpHeaders and others.
If you want to pass values between actions A and B, you may use TempData or Session is collection isn't big (it'll be stored in encrypted cookie which size cannot exceed 4k as far as I remember).
There is an another option which may be useful. You may store your collection in client's localstorage if it's ok in your case.

ASP.NET MVC Read Raw JSON Post Data

This is driving me crazy. I'm using ASP.NET MVC. I have a controller with an HttpPost action that acts as a callback URL that is called by another server (not under my control). I want to dynamically read JSON posted to it without using WebAPI or Model Binding. The URL also has a query string parameter passed to it.
The callback URL looks something like this:
http://domain.com/callback?secret=1234
I've tried reading the posted input using:
[HttpPost]
public ActionResult Callback( String secret )
{
String jsonData = new StreamReader(this.Request.InputStream).ReadToEnd();
// ...
}
However "jsonData" is always null or empty.
I just want to get the posted input and stick it into JsonFx so I can dynamically access the contents. Any ideas on how to do this the easiest possible way?
UPDATE
I've discovered the following ...
While the above DOES NOT work (jsonData will be null or empty), the following DOES if I configure what little options I have on the calling server so as to omit the "secret" query string parameter, which is about all I can do on that end since it is not my server. In this case, jsonData will have the correct posted JSON string:
[HttpPost]
public ActionResult Callback( /* String secret */ )
{
String jsonData = new StreamReader(this.Request.InputStream).ReadToEnd();
// ...
}
This is very frustrating to work around and I don't know an easy way to accept both a query string and posted JSON data on a standard MVC controller.
I have a "callback controller" with Action methods that accept various data (via GET, via form POST, via JSON POST, via JSON POST w/ a Query String, etc.) from different third-party servers. These are merchant-type callbacks where I have no control over the formats or methods used to convey information. I just need to accept the callbacks and process the information that should be there.
All of it works fine in my Controller, except the case of "JSON POST w/ a Query String".
This appears (at least to me) to be a shortcoming in standard ASP.NET MVC controllers. ???
Can anyone suggest a solution to this that can be used in a standard ASP.NET MVC controller?
Your initial approach should work if you take into consideration the fact, that ASP.NET MVC model binding has already read the stream, so you should rewind it:
[HttpPost]
public ActionResult Callback(string secret)
{
Request.InputStream.Seek(0, SeekOrigin.Begin);
string jsonData = new StreamReader(Request.InputStream).ReadToEnd();
// ...
}
Reset the position to Zero before reading the stream.
Request.InputStream.Position = 0
For ASP.NET Core 2,this works for me.
[HttpPost]
public ActionResult RawTest() {
using (StreamReader reader = new StreamReader(Request.Body, Encoding.UTF8))
{
string content = reader.ReadToEndAsync().Result;
//...
}
//...
}

a good way of passing multiple values from View to Controller

This is something happening everyday
I'm looking for a better way of grabbing the values from view into the action, since the controller create and destroy based on http request, is there a good way to pass all the params thru?(By that I mean more than 5 params)
I think about session but there is a chance pepple lose their session and the important value gone, besides session, is there any other way around?
I would first consider whether your application needs to save that much information between views. MVC is a REST based architecture, and is typically designed to be stateless.
With that said, your options for passing around state with a user boil down to Session, Cookies, and Database.
I would create a static class that stores and retrieves its data from session.
public static class CustomPersistStore
{
public static CustomClass Current{
get{
var instance = HttpContext.Current.Session["key"] as CustomClass;
if(instance = null) {
instance = new CustomClass();
}
return instance;
}
}
}
If you want to pass values from the View to the Action the best practice is to use strongly typed views.
http://howmvcworks.net/OnViews/BuildingAStronglyTypedView

Implement my own statistics engine and have a record per website visit?

I am supposed to create an internal statistics mechanism for our ASP.NET MVC 4 web application. We are not going to use external ones like Google Analytics or even Glimpse. Because I'm not sure if I can extract needed data from their API.
What we expect this mechanism is very like to Google Analytics including page hit count, referer, keyword, etc. But just for part of pages not all. We want to use these data in our own pages and reports.
Now I have 2 questions. Is it correct to ignore Google Analytics or Glimpse and implement my own? If yes, it is reasonable to save a record in database per each website visit and then use theses record to extract statistics?
Any help is highly appreciated
I think you can implement both this satistic. Its difficult to say without understanding business logic you need. But if you need more detailed information about every request (visited user roles, retrive controller/action name for some specific statistic, log access to specific resources etc.) you can easily implement this by using action filter.
public class StatisticFilter : ActionFilterAttribute
{
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
base.OnActionExecuted(filterContext);
if (filterContext.IsChildAction) //if action call was from view like #Html.Action do nothing
return;
var CurrentUser = filterContext.RequestContext.HttpContext.User;
if (CurrentUser.IsInRole("some_role"))
return; //write logic for this role
string controllerName = filterContext.ActionDescriptor.ControllerDescriptor.ControllerName;
string actionNaem = filterContext.ActionDescriptor.ActionName;
//here the id of the accessed resource - document, sale, page etc.
string id = filterContext.RequestContext.RouteData.Values["id"].ToString();
}
}
Thats all. You can extend this by any logic you need.
In my project i have the statistic table with filds:
Date - timestamp,
Controller - string,
Action - string,
id - bigint
method - string(POST, GET... if post - submited)
user_id - bigint
And insert record for every request executed. So i have most important information about request for any statistic.

Resources