Is this a bug in WebMatrix PageData?
Asked Answered
C

2

3

I think I may have found a bug in WebMatrix's PageData, but I am not sure. It concerns how to pass data from a partial page back to a calling page.

In the WebMatrix documentation (tutorials, e.g. "3 - Creating a Consistent Look", and example code), PageData is recommended as a mechanism to pass data between pages (e.g. from a content page to a layout page, or to a partial page).

However I have found that this does not always work the other way, to pass data from a partial page back to the calling page. Modifying or adding entries in PageData in a partial page, does not seem to get back to the calling page.

Cutting this right down a the simplest possible example, in a test page we may have this:

@{
    PageData["test"] = "Initial entry";
}

<p>Before calling the partial page, the test value is @PageData["test"]</p>

@RenderPage("_TestPartial.cshtml")

<p>After returning to the calling page, the test value is @PageData["test"]</p>

and in the _TestPartial.cshtml page we might have this:

@{
    PageData["test"] = "Modified entry";
}

<p>In the partial page, the test value has been modified to @PageData["test"]</p>

The resulting output is this:

Before calling the partial page, the test value is Initial entry

In the partial page, the test value has been modified to Modified entry

After returning to the calling page, the test value is Initial entry

So the modification that the partial page made to PageData is lost when you return to the calling page. The same occurs if we add new entries to PageData in the partial page. They are just lost on return to the calling page.

I don't know if this behavior a bug, or if is it intentional, but it leaves you without a clean way to pass data from a partial page back to its calling page. Is there another (relatively clean) way to do that? Alternatively, if it is a bug, is there a work around?

Chow answered 26/2, 2011 at 13:56 Comment(0)
M
8

Cross-posting my response from: http://forums.asp.net/t/1667665.aspx/1?Is+this+a+bug+in+WebMatrix+PageData+

This is going to sound trite, but the behavior is by design and not a bug. When a partial page is initalized, a copy of the PageData dictionary is passed to it, which is why the values remain unaffected in the original page.

To share values across pages and partials for the lifecycle of a request, you could use Context.Items. Alternatively, you could drop in a dictionary or an ExpandoObject inside PageData and use that to share values:

@{
    Page["Shared"] = new Dictionary<string, string>();
    Page.Shared["Title"] = "Test";
    @Page["shared"]["Title"]

    @RenderPage("~/Partial.cshtml")

    @Page.Shared["Title"]
}

// Partial.cshtml
@{
    Page.Shared["Title"] = "Updated title";
}
Margotmargrave answered 12/5, 2011 at 14:35 Comment(3)
Thanks for the answer, and it makes sense, but that behaviour is far from obvious. Where in the documentation / MSDN / whereever else would I have gone to find that out?Chow
There's a bit of documentation on how it works in MSDN - msdn.microsoft.com/en-us/library/… but it doesn't quite say much about this particular behavior.Margotmargrave
Any chance of an explanation for why the dictionary in PageData works but PageData["test"] doesn't? Is it down to by reference rather than by value?Akbar
Y
0

You layout page is overwriting the value passed to it form the partial page. To pass data from the partial page to the layout page use a different indexer.

Partial page

@{
  PageData["test"] = "value form partial";
}

Layout page

@{
  PageData["anothertest"] = "value from layout";
}
<p>test value = @PageData["test"]</p>
<p>anothertest value = @PageData["anothertest"]</p>

If you want to have a default value in the layout page that is displayed if your partial page doesn't set the value then you can do the following

Layout page

@{
  var test = PageData["test"] ?? "Layout default value";
}
<p>test value = @test</p>

Partial page

@{
  PageData["test"] = "partial page value";
}

If your partial page does not set PageData["test"] then "Layout default value" will be used

Yaws answered 26/2, 2011 at 16:33 Comment(1)
I'm sorry David, but this answer misses the point. The problem has nothing to do with layout pages. My example does not use a layout page, and there is no problem passing data from a page to a layout page.I think there may be a misunderstanding of my terminology here. By "partial page" I don't mean a page that is then wrapped in a layout page. I mean a small part of a page that is included in a larger page by use of a @RenderPage() call (as my example demonstrates). The problem is that values set into PageData a partial page are lost completely once you leave the partial page.Chow

© 2022 - 2024 — McMap. All rights reserved.