Model emptied after returning view - c#

I'm new to ASP and programing in general, so I'm probably doing something fundamentally wrong but here it goes:
Everytime I return a View in my controller the model that I was using in that controller gets emptied. example:
Account acc;
public ActionResult Index()
{
acc = new Account(accountName, password);
return View(acc)
} //At this point there still is a acc object
public ActionResult Edit(string name, string pass)
{
//Here the acc object is null
acc.userName = name;
acc.password = pass;
}
My question would how to acces the account that is currently being used or a way to save the model that was send with de View()
Edit 1
When I tried using TempDate I still encounterd the same problem:
Account acc;
public ActionResult Index()
{
acc = new Account(accountName, password);
TempDate["account"] = acc;
return View(TempDate["account"])
} //TempDate contains 1 object
public ActionResult Edit(string name, string pass)
{
//TempData is empty here
TempDate["account"].userName = name;
TempDate["account"].password = pass;
Return View("Index", TempDate["account"]);
}

Your initial observation when trying to reference acc across two requests happened because ASP.NET creates a new instance of a controller for every request. The GET for Index is one HTTP request; the GET for Edit is a separate HTTP request.
Regarding your first edit to the question, TempData is only valid during the lifetime of a single request. You'll get the same result using it in this scenario. Instead, you should use Session as described in this answer.

The duplicate suggest by Eugene is quite good if you want to try something like Cookie or Session (TempData in MVC)
If you want to store the data on application level you can maintain a collection in static class which can store the data for as long as you want.
You can maintain application level variable also for example Does asp.net MVC have Application variables?

Related

How can I make a return with parameters in a View c# asp .net mvc?

Sorry for the title, but don't know how to explain it. (.NET ASP MVC)
So what I'm trying is to create a payment request via TripleA API(redirect on their page), if the payment is successful, they will redirect on my success page with some parameters, how can I handle those parameters?
What I've tried:
public IActionResult ErrorPage(string payment_reference, string status)
{
return View(payment_reference,status);
}
https://developers.triple-a.io/docs/triplea-api-doc/dd286311a5afc-make-a-payment-request
(scroll down to success_url for more info)
To expand on Steve's comment, create a record (less code than a class) as follows...
public record ErrorViewModel(string PaymentReference, string Status);
...then use this when you send data to the view...
public IActionResult ErrorPage(string payment_reference, string status)
{
return View(new ErrorViewModel(payment_reference,status));
}
You'll need to update your view to have the following line at the top...
#model ErrorViewModel
That should be all you need.
Based on the documentation, you expect a request like this,
https://www.myshop.com/payment-success?status=paid&payment_reference=ASDDF...&order_currency=USD&order_amount=10
And you translate that into a controller method,
[HttpGet("payment-success")]
public IActionResult ResultPage(string payment_reference, string status, string order_currency, decimal order_amount)
{
var result = new ResultViewModel(payment_reference,status, order_currency, order_amount);
return View(result);
}
I also noticed that the doc says,
Note: This field is required if integrating using External URL Payment Form. For other integrations, either insert the field with a url, or remove the field completely.
So if you use External URL Payment Form integration, then I don't think you will be able to get the status and reference.
The same applies for cancel_url.

Pass created data to another controller

I am using ASP.NET MVC Entity Framework and I have a page to insert data
public ActionResult Create()
{
return View();
}
// POST: /Home/Create
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include="id,firstname,lastname,email,guests,guestfirstname,guestlastname,productInterest,occupancyTimeline,isInvestment,timeSlot,dateSlot")] CP_LC_Preview cp_lc_preview)
{
if (ModelState.IsValid)
{
db.Data.Add(cp_lc_preview);
db.SaveChanges();
return RedirectToAction("Confirm", new { info = cp_lc_preview });
}
return View(cp_lc_preview);
}
What I am trying to do is take that data that was just entered and pass it to another controller to display. like a confirmation page.
Here is my method for the confirm page
public ActionResult Confirm()
{
return View();
}
You may consider following the PRG pattern.
PRG stands for POST - REDIRECT - GET. With this approach,After you successfully save the data, you will issue a redirect response with a unique id in the querystring, using which the second GET action method can query the resource again and return something to the view.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include="id,firstname,lastname,email,guests,guestfirstname,guestlastname,productInterest,occupancyTimeline,isInvestment,timeSlot,dateSlot")] CP_LC_Preview cp_lc_preview)
{
if (ModelState.IsValid)
{
db.Data.Add(cp_lc_preview);
db.SaveChanges();
var id = cp_lc_preview.Id;
return RedirectToAction("Confirm", new { id = id });
}
return View(cp_lc_preview);
}
and in your Confirm action method, have id parameter and using the value of that read the record from the db again and use as needed.
public ActionResult Confirm(int id)
{
var d = db.Data.FirstOrDefault(g=>g.Id==id);
// Use d as needed
// to do : Return something
}
TempData
If you do not prefer to have this id in the url, consider using TempData to pass the data. But TempData has a short life span. Once read, the data is gone. TempData uses Session behind the scene to store the data.
TempData["NewItem"] = cp_lc_preview;
return RedirectToAction("Confirm", "controllerName");
and in the Confirm method
public ActionResult actionname()
{
var model=TempData["NewItem"] as CP_LC_Preview
// to do : Return something
}
For your reference
How do I include a model with a RedirectToAction?
You can use TempData for that.
TempData["YourData"] = YourData;//persist data for next request
var myModel=TempData["YourData"] as YourData //consume it on the next request
What is TempData ?
TempData is meant to be a very short-lived instance, and you should only use it
during the current and the subsequent requests only.
Since TempData works this way, you need to know for sure what the next request will be, and
redirecting to another view is the only time you can guarantee this.
Therefore, the only scenario where using TempData will reliably work is when
you are redirecting.This is because a redirect kills the current request , then creates a
new request on the server to serve the redirected view.
Simply said, Asp.Net MVC TempData dictionary is used to share data between
controller actions.
The value of TempData persists until it is read or until the current user’s session times out.
By default, the TempData saves its content to the session state.
TempData values are marked for deletion when you read them. At the end of the request,
any marked values are deleted.
The benefit is that if you have a chain of multiple redirections it won’t cause TempData to
be emptied the values will still be there until you actually use them, then they clear up after
themselves automatically.

How to use sessions,Tempdata in asp.net mvc4

I am working on asp.net with mvc 4 architectute. Here i have two controller Display and SessionEx. In Display Controller i have an method like below
public ActionResult SessionExample()
{
TempData["FortheFullRequest"] = "FortheFullRequest";
string v = Session["Session1"].ToString();
ViewData["Myval"] = "ControllertoView";
ViewBag.MyVal = "ControllertoView";
Session["Testing1"] = "Testing Session";
return RedirectToAction("SomeOtherAction", "SessionEx");
}
In the SessionEx controller i have the method as below
public ActionResult SomeOtherAction()
{
string str1 = Convert.ToString(Session["Testing1"]);
string str2 = Convert.ToString(TempData["FortheFullRequest"]);
return View();
}
I am debugging the project and i have also used watch to look at the gets stoted in tempdata and session. In the start the appropriate value in both session and tempdata but when the cursor reaches at RedirectToAction method all values gets stored in session and tempdata becomes null.Please help me someone here.
If you want to store data that will be used after a redirect is made to another action method, then use Session.
TempData is mainly for one-time, short-lived, requests as discussed in this this SO question
You are likely finding that the data in TempData is not there after you have redirected to SomeOtherAction(), which is by desing with how TempData works.
To be honest, I never use TempData, I don't see the point myself.

TempData[] getting wiped despite no requests taking place

TempData is supposed to persist for a subsequent request. However when I check the TempData in a subsequent controller I get a null. Why is TempData[] getting wiped off. Here are my two controllers. I am calling them in succession. So TempData[] should persist from one request to the next. Here is code from controller 1:
[HttpGet]
public ActionResult EditCampaign(int? Id)
{
ViewBag.Banner = bannerText.Replace(" ", " ");
// This is passed in case we need to add a new product or edit one. Then we'll
// need the campaign id for reference purposes.
TempData["campaign_id"] = Id;
TempData["campaignBanner"] = bannerText.Replace(" ", " ");
ViewBag.StartDate = debugger.startDate.ToShortDateString();
ViewBag.EndDate = debugger.endDate.ToShortDateString();
int Id1 = Convert.ToInt32(TempData["campaign_id"]);
int convertedId1 = Id1
Here is where I try to get the value in Controller 2:
[HttpPost]
public ActionResult EditCampaign(CampaignDTO camps)
{
// Do this up top. i.e. get the campaign ID
camps.Id = Convert.ToInt32(TempData["campaign_id"]);
string success = "";
I suspect that assigning the value of TempData in the penultimate line of controller 1 might be wiping off the data. If thats the case that is something new and not documented. Please help.
Reading the data is enough to remove it. Here's the relevant source:
public object this[string key]
{
get
{
object value;
if (TryGetValue(key, out value))
{
_initialKeys.Remove(key);
return value;
}
return null;
}
set
{
_data[key] = value;
_initialKeys.Add(key);
}
}
So in controller 1, when you say:
int Id1 = Convert.ToInt32(TempData["campaign_id"]);
you are actually removing the data you just inserted.
There are many ways to work around this, but if you must read it from TempData, use Peek() instead.
You have some flawed info. The data stored in the TempData property persists for only one request.
http://msdn.microsoft.com/en-us/library/system.web.mvc.viewpage.tempdata%28v=vs.118%29.aspx
TempData is useful when you are redirecting (HTTP 302 or 303, i.e. RedirectToAction in MVC) to pass along some context. It does not persist across separate HTTP requests. Based on your code sample, it suggests your client code first makes a GET to controller one, then issues a second request to controller two.
Your best bet is probably to return the necessary data as part of your response in controller one, then make that part of the incoming request to controller. You could potentially also use Session variables, https://code.msdn.microsoft.com/How-to-create-and-access-447ada98.

should this mvc action be trimmed down

I'm just getting into mvc 4 (and mvc in general) and am just wondering is this action code ok or should it be stripped down again?
[HttpPost]
public ActionResult Index(DashboardViewModel dbModel)
{
//retrieve latest resident order
var residentOrder = db.ResidentOrders.GetById(dbModel.ResidentOrderID);
if (residentOrder == null)
{
var order = db.Orders.GetById(dbModel.OrderID);
var user = db.Users.GetUserByUsername(User.Identity.Name);
residentOrder = new ResidentOrder()
{
CreatedDate=DateTime.Now,
LastUpdateDate = DateTime.Now,
Litres=0,
Customer = user
};
order.ResidentOrders.Add(residentOrder);
db.Commit();
}
//check to see if value has changed
if (!dbModel.ResidentLitresOrdered.Equals(residentOrder.Litres))
{
//get new ordered value
residentOrder.Litres = dbModel.ResidentLitresOrdered;
db.Commit();
//send an email just to notify in writing of the change.
SendOwnOrderQtyUpdateNotification();
}
return View(dbModel);
}
Basically if a resident order doesnt exist then we create one, this is the only place in the system where this would need to happen.
Should I still be stripping that code out into my repositories?
db is my IUnitOfWork btw
I would recommend that you create a "repository" to hide the details from the Controller action.
An "Upsert" method would allow this to be clearly and elegantly implemented hiding the details from the controller.

Categories

Resources