Redirect to action passes null instead of object - asp.net-mvc-4

My MVC4 project uses the RedirectToAction() to pass values to another controller.
The problem is, it passes null instead of a value
[HttpGet]
public ActionResult MyProduct(product prod)
{
return RedirectToAction("Index", "MyController", new { prod = prod});
}
This accurately redirects to my MyController which is
public ActionResult Index(Product prod)
{
// prod is null :(
}
I put on a watch in the MyProduct controller, the prod object has a value. The properties do not have values :( it is null
Why does it become null when I pass the object between controllers?

You mistyped you parameter name that you are expecting at your action change it to prod because the prod is a part of RouteValueDictionary which will be collected by the same parameter as defined askey in the dictionary
return RedirectToAction("Index", "MyController", new { prod = prod});
Update
You cannot pass a model object via route parameters via RedirectToAction if I understood your question correctly, instead you can pass specific properties required to be send or you can use the TempData
You can't send data with a RedirectAction. That's because you're doing a 301 redirection and that goes back to the client.
When you redirect you mainly have the query string as a means to pass data to the other request. The other approach is to use TempData which stores data away on the server and you can retrieve it on the next request. By default TempData uses Session.
Consider this image for getting the ways of passing data between Model-View-Controller

Your function parameter name doesn't match in your RedirectToAction().
You should change it like this:
return RedirectToAction("Index", "MyController", new { prod = prod});

Related

Passed value is not preserved

Not MVC!
Hi all,
What am I doing wrong here...
Im trying to pass an integer value from the onPost method of a Razor Page(Scores/Create.cshtml) to the onGet method of another page(/Scores/Index.cshtml) however the value is not being preserved and I either get null or 0 when inspecting the id value in the onGet method depending on how I send the integer.
I know this works using routes as I do this on another page
<a asp-page="/Scores/Index" asp-route-id="#item.ElementId">Update scores</a>
I have tried passing the value from an entity property like in the code example below, from ViewData variable, also from a locally created integer and finally just passing an integer value itself. In all cases the value is correct in the OnPost but never gets to the onGet.
The OnPost
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
_context.TScores.Add(TScores);
await _context.SaveChangesAsync();
return RedirectToPage("./Index","OnGet",TScores.ElementId);
}
The OnGet
public async Task OnGetAsync(int? id)
{
TElements telement = new TElements();
telement = _context.TElements.Where(a => a.ElementId == id).FirstOrDefault();
I have also tried it without setting the OnGet method name in the RedirecttoPage
I am expecting to get the value of id in the onGet to match TScores.ElementID passed from the onPost.
Thanks in advance
D
The parameter requires an object, specifically an anonymous object of route values; it doesn't know what to do with an int.
return RedirectToPage("./Index", new { id = TScores.ElementId });

Route to allow a parameter from both query string and default {id} template

I have an action in my ASP.Net Core WebAPI Controller which takes one parameter. I'm trying to configure it to be able to call it in following forms:
api/{controller}/{action}/{id}
api/{controller}/{action}?id={id}
I can't seem to get the routing right, as I can only make one form to be recognized. The (simplified) action signature looks like this: public ActionResult<string> Get(Guid id). These are the routes I've tried:
[HttpGet("Get")] -- mapped to api/MyController/Get?id=...
[HttpGet("Get/{id}")] -- mapped to api/MyController/Get/...
both of them -- mapped to api/MyController/Get/...
How can I configure my action to be called using both URL forms?
if you want to use route templates
you can provide one in Startup.cs Configure Method Like This:
app.UseMvc(o =>
{
o.MapRoute("main", "{controller}/{action}/{id?}");
});
now you can use both of request addresses.
If you want to use the attribute routing you can use the same way:
[HttpGet("Get/{id?}")]
public async ValueTask<IActionResult> Get(
Guid id)
{
return Ok(id);
}
Make the parameter optional
[Route("api/MyController")]
public class MyController: Controller {
//GET api/MyController/Get
//GET api/MyController/Get/{285A477F-22A7-4691-AA51-08247FB93F7E}
//GET api/MyController/Get?id={285A477F-22A7-4691-AA51-08247FB93F7E}
[HttpGet("Get/{id:guid?}"
public ActionResult<string> Get(Guid? id) {
if(id == null)
return BadRequest();
//...
}
}
This however means that you would need to do some validation of the parameter in the action to account for the fact that it can be passed in as null because of the action being able to accept api/MyController/Get on its own.
Reference Routing to controller actions in ASP.NET Core

Appending hash/fragment to RedirectResult results in cumbersome code

The code works but is silly.
When the View is returned to the user the page scrolls to the companyId anchor.
Silly is that I have to expose another public action with another route (without 'terms')
I want to redirect to /terms/companyId but then I get an ambigiousAction exception that this action with same routes already exists...
How to solve that dilemma if possible not change the first route?
[HttpGet("~/terms/{companyId}")]
public IActionResult Home(string companyId})
{
string url = Url.Action(nameof(HomeForRedirect), new { companyId}) + "#conditions";
return new RedirectResult(url);
}
[HttpGet("{companyId}")]
public IActionResult HomeForRedirect(string companyId)
{
Viewbag.CompanyId = companyId;
return View(nameof(Home));
}
If I'm understanding your code, you essentially want the URL /terms/{companyId} to redirect to /{controller}/{companyId}#conditions? The easiest path would be to attach both routes to the same action and do the redirect in a conditional. Something like:
[HttpGet("{companyId}", Order = 1)]
[HttpGet("~/terms/{companyId}", Order = 2)]
public IActionResult Home(string companyId)
{
if (Context.Request.Path.StartsWith("/terms"))
{
var url = Url.Action(nameof(Home), new { companyId }) + "#conditions";
return Redirect(url);
}
ViewBag.CompanyId = companyId;
return View();
}
An even better method would be to simply do the redirect directly in IIS. There's a not insignificant amount of processing that needs to occur to handle a request in ASP.NET Core machinery, and it's totally wasted effort simply to redirect. Use the URL Rewrite module in IIS to set up your redirect for this URL, and then your application doesn't have to worry about it at all. You just have your normal run-of-the-mill Home action that returns a view, and everything will just work.
A few other notes since it seems like you're new to this:
It's better to use the Route attribute rather than the more specific HttpGet etc. The default is GET.
Return the controller methods like Redirect rather than instances of IActionResult (i.e. new RedirectResult(...)).
The default is to return a view the same name as the action. So, assuming your action is Home, you can just do return View(), rather than return View(nameof(Home)).

Redirecting to an Action Method from another Action Method in the same controller

I am a Newbie in asp.net and currently I am doing a web page application in MVC4 with Login functionality.
My Index action method looks like this-
public ActionResult Index()
{
var PageModelList1 = new DataAccessLayer.DataAccess().GetPageInfo();
ViewData["MenuList"] = PageModelList1.PageModelList;
return View();
}
and my LogIn action method looks like-
[HttpPost]
public ActionResult LogIn(LogInModel model, string returnUrl)
{
if (ModelState.IsValid)
{
var PageModelList1 = new DataAccessLayer.DataAccess().GetPageInfo(model.UserName,model.Password);
ViewData["MenuList"] = PageModelList1.PageModelList;
return RedirectToAction("Index", "MyController");
}
ModelState.AddModelError("", "login failed");
return PartialView("_LogIn", model);
}
what I need is, when I Login successfully, the RedirectToAction("Index", "Deimos") should take place but the 'MenuList' there should be the new 'MenuList' from LogIn action method. How could I do it?
RedirectToAction will send a 302 response to the browser with the new url as the location header value and browser will make a totally new request to go to that page. This new request has no idea what you did in the previous request. So ViewData will not work. You may consider using TempData.
But TempData's life is only until the next request. After that it is gone. So if you want something on all the subsequent requests(like a menu to be shown to user), I suggest you read it from a database table every time you load the page. You can store the items to a cache after the first read to avoid constant hit(s) to the database if you are worried about that.
Another option is to set the menu items to Session variables and read from there. I am not a big fan of setting stuff like that to session. I prefer to read it from a cache (in which data was loaded from a db call) or so.

Data is not inserting to the database

I am new to asp .net MVC 4.
I have one text box and the text box value I am fetching from one table.But while clicking on submit button this value I want to insert into different table , which is not inserting and showing error.It is taking value as null.
coding
View
#Html.TextBox("empname", (string)ViewBag.empname, new { #readonly = "readonly" })
controller
[HttpGet]
public ActionResult Facilities()
{
mstEmpDetail emp = new mstEmpDetail();
emp = db.mstEmpDetails.Single(x => x.intEmpId == 10001);
ViewBag.empname = emp.txtEmpFirstName;
return View();
}
[HttpPost]
public ActionResult Facilities(TrnBusinessCardDetail bc)
{
var empname1 = ViewBag.empname;
bc.txtfirstName = empname1;
db.TrnBusinessCardDetails.Add(bc);
db.SaveChanges();
return RedirectToAction("Facilities");
}
While I was working with normal text box it was inserting properly,but when I have retrieve
fro DB then i am getting this problem ?
How to solve this problem ?
Viewbag is a one way street - you can use it to pass information to the view, but you cannot use it to get the information from the view. The statement ViewBag.empname in your POST method has a value of null in your code.
As suggested by #dotnetom, ViewBag is a one way street. MVC is stateless so a POST request is not a "Round Trip" from previous get request. Thus your ViewBag can not hold its state.
MVC can determine (and construct) your action parameters from Form Parameters. In your case you have added a textbox with name "empname". So you should get this value as parameter in your POST request.
[HttpPost]
public ActionResult Facilities(TrnBusinessCardDetail bc, string empname)
{
bc.txtfirstName = empname;
db.TrnBusinessCardDetails.Add(bc);
db.SaveChanges();
return RedirectToAction("Facilities");
}
This would be simplest of solution given your problem. More appropriate would be binding your textbox directly with you model property. This way you will not have to worry about retrieving and assigning property value to model in your controller.
I think the problem is when you are using var empname1 = ViewBag.empname; in post controller because ViewBag.empname lost its value at that time.