Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Class instance as parameter #17210

Closed
mrlife opened this issue Mar 4, 2020 · 16 comments · Fixed by #17571
Closed

Class instance as parameter #17210

mrlife opened this issue Mar 4, 2020 · 16 comments · Fixed by #17571
Assignees
Labels
Blazor doc-enhancement needs-more-info Pri1 High priority, do before Pri2 and Pri3 Source - Docs.ms Docs Customer feedback via GitHub Issue
Projects

Comments

@mrlife
Copy link
Contributor

mrlife commented Mar 4, 2020

[EDIT by guardrex Note to self ... see 👉 https://github.com/dotnet/aspnetcore/issues/19605]

A class instance (that has public properties that are set by a default constructor) as a parameter causes the razor component to not be displayed.

Can the following quote be confirmed?

The parameter type must be JSON serializable, which typically means that the type must have a default constructor and settable properties.

I checked if it was JSON serializable with the following, and it serializes it as expected. I also included the call to the <component />.

Code

var myObject = new MyClass(5, "test");
var serialized = Newtonsoft.Json.JsonConvert.SerializeObject(myObject);
<component type="typeof(MyComponent)" render-mode="Server" param-MyObject="myObject" />

MyClass

public class MyClass
{
	public int MyInt { get; set; }
	public string MyString { get; set; }

	public MyClass(int myInt, string myString)
	{
		MyInt = myInt;
		MyString = myString;
	}
}

MyComponent

@MyObject.MyInt, @MyObject.MyString

@code
{
	[Parameter]
	public MyClass MyObject { get; set; }
}

Document Details

Do not edit this section. It is required for docs.microsoft.com ➟ GitHub issue linking.

@dotnet-bot dotnet-bot added ⌚ Not Triaged Blazor Source - Docs.ms Docs Customer feedback via GitHub Issue labels Mar 4, 2020
@guardrex guardrex added this to Triage in Blazor.Docs via automation Mar 4, 2020
@guardrex guardrex added this to the Backlog milestone Mar 4, 2020
@guardrex guardrex self-assigned this Mar 4, 2020
@guardrex guardrex moved this from Triage to P0/P1 - High Priority in Blazor.Docs Mar 4, 2020
@guardrex guardrex added the Pri1 High priority, do before Pri2 and Pri3 label Mar 4, 2020
@guardrex guardrex modified the milestones: Backlog, 2020 Q1 ends Mar 31 Mar 4, 2020
@guardrex
Copy link
Collaborator

guardrex commented Mar 4, 2020

Hello @mrlife ... I'll need to do some more work to that one. It came straight over from engineering content, and I didn't have time to do much with it. 🏃 I'll probably work this one with the other one 👉 #17160 ... but it will be perhaps a week or so before I can get to it due to high priority issues that must be resolved first.

To make that example work ...

  • Make THs available to the page with @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers.
  • Use ServerPrerendered rendering mode.
  • Since it looks like you want to pass myObject as a local var in the page, make it param-MyObject="@myObject" and place a @{ var myObject = ... } there.
  • ... and I guess u were just hacking around with the serialized var ... u don't need that.
  • Sacrifice a MS ergonomic keyboard to the 🙏 server gods 🙏. 😄
  • It should ✨ Just Work!™️ ✨

@mrlife
Copy link
Contributor Author

mrlife commented Mar 5, 2020

@guardrex Thanks! The bit about using ServerPrerendered does seem to help some... the content is displayed due to the prerendering, though an error is thrown in the browser console. I opened a ticket with engineering here: dotnet/aspnetcore#19605.

@guardrex
Copy link
Collaborator

guardrex commented Mar 5, 2020

I'll double check ... I don't recall an error, but it might be there. I'll let u know (and on that issue, too).

@guardrex
Copy link
Collaborator

guardrex commented Mar 5, 2020

No error here. Console is clean, but it does only work (thus far) with ServerPrerendered.

@mrlife
Copy link
Contributor Author

mrlife commented Mar 5, 2020

To close the loop on this and the attached engineering issue, this is the way it works for me without throwing an error.

MyClass.cs

public class MyClass
{
	public int MyInt { get; set; }
	public string MyString { get; set; }

	// this would be created by compiler if left out
	public MyClass() { }
}

Index.cshtml

@{
	var myObject = new MyClass();
	myObject.MyInt = 1;
	myObject.MyString = "test";
}

<component type="typeof(MyComponent)" render-mode="Server" param-MyObject="myObject" />

Just in case, here are the details for my dotnet install, not sure if different than yours...

$ dotnet --info
.NET Core SDK (reflecting any global.json):
Version: 3.1.102
Commit: 573d158fea

Runtime Environment:
OS Name: Mac OS X
OS Version: 10.15
OS Platform: Darwin
RID: osx.10.15-x64
Base Path: /usr/local/share/dotnet/sdk/3.1.102/

Host (useful for support):
Version: 3.1.2
Commit: 916b5cba26

.NET Core SDKs installed:
3.1.102 [/usr/local/share/dotnet/sdk]

.NET Core runtimes installed:
Microsoft.NETCore.App 3.1.2 [/usr/local/share/dotnet/shared/Microsoft.NETCore.App]

@guardrex
Copy link
Collaborator

guardrex commented Mar 5, 2020

Ok ... I'll give that a shot here. 🤞

@guardrex
Copy link
Collaborator

guardrex commented Mar 5, 2020

That doesn't work here. I've never been able to get the Server render mode to work here. I get a blank page, but I can see in the markup the placeholders for my three test components ...

Capture

@{
    var myObject = new MyClass();
    myObject.MyInt = 6;
    myObject.MyString = "Set by MyPage";
}

<component type="typeof(MyComponent)" render-mode="Server" param-MyObject="myObject" />

<component type="typeof(MyComponent2)" render-mode="Server" param-MyInt="12345" />

<component type="typeof(MyComponent3)" render-mode="Server" />

... or with an @myObject attribute value.

All three work with ServerPrerendered and the non-parameterless ctor (pardon the double-negative 😄) ...

Capture

Capture

@{
    var myObject = new MyClass(6, "Set by MyPage");
}

<component type="typeof(MyComponent)" render-mode="ServerPrerendered" param-MyObject="@myObject" />

<component type="typeof(MyComponent2)" render-mode="ServerPrerendered" param-MyInt="12345" />

<component type="typeof(MyComponent3)" render-mode="ServerPrerendered" />

.... soooooooo ... if I don't get clarification, I can only guess at what to say. We might have to wait a week or two for the dust to settle on their current workload. They're all 🏃😅 right now.

@pranavkm
Copy link
Contributor

pranavkm commented Mar 5, 2020

@guardrex it's the missing parameter-less constructor. Do you think we can add a section about this to our docs? If you had Debug logs enabled, it should tell you what went wrong, the surfaced error message is not helpful.

Something to the effect of if you see The list of component records is not valid.

a) If you're running locally, turn on Debug logs for Microsoft.AspNetCore.Components and refresh the page. It should indicate more details about what failed.
b) If you've deployed your application to production and are using a load balancer, make sure you've enabled sticky sessions. Link to Azure SignalR Service configuration

@guardrex
Copy link
Collaborator

guardrex commented Mar 5, 2020

So, we've clarified that it's supposed to work with both Server and ServerPrerendered modes. I understand that point.

I've tried what's been suggested regarding the parameterless ctor. No VS output errors (with debug component logging) and no console errors ... but I'm not getting component output. Here's the full set up that I have ...

MyClass.cs

public class MyClass
{
    public MyClass()
    {
    }

    public int MyInt { get; set; } = 999;
    public string MyString { get; set; } = "Initial value";
}

Shared/MyComponent.razor

<h2>MyComponent</h2>

<p>MyInt: @MyObject.MyInt</p>
<p>MyString: @MyObject.MyString</p>

@code
{
    [Parameter]
    public MyClass MyObject { get; set; }
}

Pages/MyPage.cshtml

@page "/MyPage"
@model BlazorServer31.MyPageModel
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@using BlazorServer31
@using BlazorServer31.Shared
@{
    Layout = null;
}

<!DOCTYPE html>
<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>MyPage</title>
</head>
<body>
    @{
        var myObject = new MyClass();
        myObject.MyInt = 7;
        myObject.MyString = "Set by MyPage";
    }

    <component type="typeof(MyComponent)" render-mode="Server" param-MyObject="@myObject" />
</body>
</html>

What's wrong with that ☝️?

Additionally, it's still not clear to me why the parameterless ctor is required in the ServerPrerendered case. It works here in that scenario. If I use that setup ☝️ and only change render-mode="Server" to render-mode="ServerPrerendered", it works ...

Capture

... my point is just that the doc can't say "a parameterless ctor is required" when it isn't. I'm missing some understanding. 😕

@mrlife
Copy link
Contributor Author

mrlife commented Mar 5, 2020

@guardrex Is your result of dotnet --info different than mine?

$ dotnet --info
.NET Core SDK (reflecting any global.json):
Version: 3.1.102
Commit: 573d158fea

Runtime Environment:
OS Name: Mac OS X
OS Version: 10.15
OS Platform: Darwin
RID: osx.10.15-x64
Base Path: /usr/local/share/dotnet/sdk/3.1.102/

Host (useful for support):
Version: 3.1.2
Commit: 916b5cba26

.NET Core SDKs installed:
3.1.102 [/usr/local/share/dotnet/sdk]

.NET Core runtimes installed:
Microsoft.NETCore.App 3.1.2 [/usr/local/share/dotnet/shared/Microsoft.NETCore.App]

@guardrex
Copy link
Collaborator

guardrex commented Mar 5, 2020

Same ... I'm on 3.1.102 ... but Windows.

@pranavkm
Copy link
Contributor

pranavkm commented Mar 5, 2020

What happens when you change the class as so:

public class MyClass
{
    public MyClass(string x)
    {
    }

    public int MyInt { get; set; } = 999;
    public string MyString { get; set; } = "Initial value";
}

@guardrex
Copy link
Collaborator

guardrex commented Mar 5, 2020

After also updating to ...

var myObject = new MyClass(string.Empty);

Same result .... nothing rendered ....

Capture

@pranavkm
Copy link
Contributor

pranavkm commented Mar 5, 2020

Is this with ServerPrerendered?

@guardrex
Copy link
Collaborator

guardrex commented Mar 6, 2020

No, just Server.

ServerPrerendered always worked for me ... both with and without the parameterless ctor.

@guardrex
Copy link
Collaborator

guardrex commented Apr 1, 2020

It's still misbehaving for Blazor Server with a render-mode of Server. No console errors in the browser, but nothing is rendered.

<html><head>
    <meta name="viewport" content="width=device-width">
    <title>MyPage</title>
</head>
<body>

    <!--Blazor:{"sequence":0,"type":"server","descriptor":"CfDJ8OjqziBPZk1MjaFG6MZVV6W5US\u002Bqz8xZZJdyqSHc3Ym8gB92wvA3xU4jOJVN38wAi1X7Z1lIdg8XDvRzlZlFMgigWNAUxar7rViXiaKs3MpBEs2/CDivdJC9FEMFB5sh85rzjkEsB1UVy/VaWy/6Pamie4edJqKH389gNML201PeeXaE4XAj4qWnUXTm/BYBMl9mBOKjdbOd7LGZANKXsScBeHd2Dmbv/z\u002Bm93WpWo4HT1udMtNarRC9EIrML0pUElE1yvE4twm/dB64hLq8sMZ2sONJ87y1pwSTGmLQij\u002BYH6Yu63cpv\u002BJIK9v9nuGmijrRhULI8YGtNJ/EMCHl6WmAsIbuxjhfaRvsJ7HqMxWShpZnzYZKG66mrpf3RNEmlzTiYKEvP3xD8uIdXWC6OkKEpmxelrJ4\u002BsbeBOkeu22yGbALhoqhi\u002By/Hozi9iM0ija6jkS4XS3cmVDuTl34ln/DpeGCaY/IG1pM8HnkeVyA3MS7ceJ7SHU39f1y8FRKQFtJfV0G1DNTowfV\u002BDXfd6E0umT/HXhJZuQT3fbXefPXdRB5C6NueT3cBOlwmxb\u002B0g=="}-->


</body></html>

Capture

BUT... let's go ahead and document it for ServerPrerendered to improve the coverage for what we know otherwise.

I'll mark the PR as "addressing" this issue to keep it open until we know what's what.

EDIT

a) If you're running locally, turn on Debug logs for Microsoft.AspNetCore.Components and refresh the page. It should indicate more details about what failed.

I'll take a look at that again and report back here.

EDIT

Ok ... I figured out what I was missing. The page that I created in the test app didn't have the blazor.server.js script! 👦🔫

Ok ... I can get the PR in now.

@guardrex guardrex moved this from P0/P1 - High Priority to In progress in Blazor.Docs Apr 1, 2020
Blazor.Docs automation moved this from In progress to Done Apr 10, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Blazor doc-enhancement needs-more-info Pri1 High priority, do before Pri2 and Pri3 Source - Docs.ms Docs Customer feedback via GitHub Issue
Projects
Archived in project
Blazor.Docs
  
Done
Development

Successfully merging a pull request may close this issue.

4 participants