39

I'm developing a web application using ASP.NET Core 2.0 with Razor Pages. I'm creating an object with some data and want to send that object to another page. I'm doing this:

var customObject = new{ //some values }; return RedirectToPage("NewPage", customObject); 

I see that the URL has the values of the object I'm sending, but I can't find how to take that values (in the NewPage instance).

How do I share objects between Razor Pages? Is this the correct way to achieve it?

5
  • send the object on when you post it back from the view to the controller Commented Oct 16, 2017 at 14:28
  • 1
    So it begins. The scourge of Web Forms, reborn as Razor Pages. When things are "magic", it's no longer obvious how to do simple things like this. Razor Pages or no, it works the same as any other HTTP request. You must post the values to the new URL, and then retrieve the data from the request body on the resulting URL. Commented Oct 16, 2017 at 15:05
  • 1
    Parameters in a query string isn't exactly "magic" -- and that's all handlers and parameter-passing are for data-sharing via GET in Razor Pages. Commented Jan 17, 2018 at 10:23
  • I am trying pretty hard to avoid Razor Pages, but even in my MVC Core 2.2 app the Identity scaffolding forced me to use Razor all over. Any way to avoid that? (easily?) Commented Jan 28, 2019 at 4:05
  • 3
    No way to avoid Razor Pages. I tried rewriting the Identity scaffolding in MVC and gave up. I begrudgingly have accepted that Razor Pages are here to stay and where MS wants us to head so might as well get over and and accept them. Commented May 20, 2019 at 17:51

6 Answers 6

63

You can pass parameters to specified handlers in the page model class, like this:

return RedirectToPage("Orders", "SingleOrder", new {orderId = order.Id}); 

Where the page model class method has this signature:

public void OnGetSingleOrder(int orderId) 

If you are passing an object, you can pass the object directly, but in my experience any child objects are not populated.

Sign up to request clarification or add additional context in comments.

2 Comments

I agree. This is the correct answer. I've tested it with multiple key value pairs, and it works like a charm each time. You may also want to consider using session state.
this is the page that describes it: learn.microsoft.com/en-us/dotnet/api/…
14

The key here is that you need to pass an anonymous object whose property names match the routing constraints defined in the Razor Page.

For example, if you define an id (optional) routing constraint in the Razor Page:

@page "{id?}"

To redirect to that view passing a specific id, just do:

return RedirectToPage("PageName", new { id = 3 }); 

If you just one to redirect to the current page (but passing a specific id), just do:

return RedirectToPage(new { id = 3 }); 

If you just pass the number without the anonymous object it won't work.

2 Comments

Just to add, when you are redirecting to the same page: if any of the parameters to the page handler come from the route, you can omit them. For example if the OnGet looks like: public async Task<IActionResult> OnGet([FromRoute]string userId, [FromQuery]bool? cs = null) When redirecting from the same page just do: return RedirectToPage(new { cs = true });
Why not just use Page() instead of RedirectToPage() for returning the current page? Can you not use arguments in Page() or something? Seems inefficient to do all the "redirect" logic if you're just updating/loading the current page.
8

Pass object from one page to another through Anchor Tag Helper.

  1. Model class.

    public class Car { public int ID { get; set; } public string Name { get; set; } public string Model { get; set; } public string Description { get; set; } } 
  2. Cars - PageModel.

    public class CarsModel : PageModel { public List<Car> Cars { get; private set; } = new List<Car> { new Car{ ID = 1, Name = "Car1", Model = "M1", Description = "Some description" }, new Car{ ID = 2, Name = "Car2", Model = "M2", Description = "Some description" }, new Car{ ID = 3, Name = "Car3", Model = "M3", Description = "Some description" }, new Car{ ID = 4, Name = "Car4", Model = "M4", Description = "Some description" } }; } 
  3. Cars - RazorPage(source of the pass-object) -> display all items(in our case cars) from the list of 'CarsModel'. In the 'Anchor Tag Helper' use 'asp-all-route-data' attribute, which is initialized with dictionary name as string(in our case 'dictCars').

    @page @using Newtonsoft.Json @model CarsModel @{ ViewData["Title"] = "Cars"; } <table> <thead> <tr> <th> @Html.DisplayNameFor(model => model.Cars[0].Name) </th> <th> @Html.DisplayNameFor(model => model.Cars[0].Model) </th> <th></th> </tr> </thead> <tbody> @foreach (var car in Model.Cars) { Dictionary<string, string> dictCars = new Dictionary<string, string> { { "passedObject", JsonConvert.SerializeObject(car) } }; <tr> <td> @Html.DisplayFor(modelItem => car.Name) </td> <td> @Html.DisplayFor(modelItem => car.Model) </td> <td> <a asp-page="./Details" asp-all-route-data="dictCars">Details</a> </td> </tr> } </tbody> </table> 
  4. Details - PageModel(destination of the pass-object).

    public class DetailsModel : PageModel { public Car Car { get; set; } public IActionResult OnGet(string passedObject) { Car = JsonConvert.DeserializeObject<Car>(passedObject); if (Car == null) { return NotFound(); } return Page(); } } 
  5. Details - RazorPage.

    @page @model DetailsModel @{ ViewData["Title"] = "Car Details"; } <h2>Details</h2> <div> <h4>Car</h4> <hr /> <dl class="dl-horizontal"> <dt> @Html.DisplayNameFor(model => model.Car.Name) </dt> <dd> @Html.DisplayFor(model => model.Car.Name) </dd> <dt> @Html.DisplayNameFor(model => model.Car.Model) </dt> <dd> @Html.DisplayFor(model => model.Car.Model) </dd> <dt> @Html.DisplayNameFor(model => model.Car.Description) </dt> <dd> @Html.DisplayFor(model => model.Car.Description) </dd> </dl> </div> 

Comments

6

You can use the TempData decorator. It is available as a decorator or as a dictionary and its purpose is to keep an object between requests. In the background, the value is stored in a cookie or in the user session, at your choice. You can see more details about its use in the links below:

TempData at Microsoft Documentation
TempData in Learn Razor Pages (more practical)

Comments

0

I don't know if that might help you or it is good practice for MVVM flavours like Razor, but inside ASP.NET Core API projects I often use custom global DI'ed services, like

public void ConfigureServices(IServiceCollection services) { ... services.AddSingleton<IMyService, MyService>(); ... services.AddMvc(); } 

You can exchange data between your IndexModel and a CustomModel eg. by setting it like

public class CustomModel : PageModel { public IMyService _myService; public CustomModel(IMyService myService) { _myService = myService; } public async Task<IActionResult> OnPostAsync(...) { ... _myService.SetDataOrSometing(...); ... return RedirectToPage(); } } 

and retrieving it like

public class IndexModel : PageModel { public IMyService _myService; public IndexModel(IMyService myService) { _myService = myService; } public void OnGet() { var data = _myService.GetDataOrSomething(); } } 

From here you can also use an ObserveableCollection and register events to get the updates down to your PageModels.

IMHO this is a way to pass objects from one page to another with a clean separation of concerns.

5 Comments

How do you know which client put which data to there? If and only if one client is using the system, then there is no problem. You can use IMemoryCache with a lifetime. The approach defined in this answer is not a good practice.
Agreed: hillstuk gave the "correct answer" for passing data between ASP.Net Core MVC Razor views Specifically: 1) Define a view model. It can be a POCO. Put it in your "Models" folder. 2) Declare the view model in your view's parameter list. 3) Create an anonymous instance in your RedirectToPage() call.
Though it's old, the accepted answer is also not working in a distributed system with multiple nodes, if the singleton service is not using some other mechanism to store the data for every node. It also needs to delivers a unique key for retrieval for exactly that users+requests data.
Can we use this approach with Transient not singleton?
A clientside solution applied to a multithreaded server application. What could go wrong?
0

Use the "Redirect" method:

return Redirect("/Home/NewPage?id=" + customObject.Id); 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.