https://discord.umbraco.com logo
#help-with-umbraco
model binding with ViewComponents and BeginUmbracoForm
# help-with-umbraco
z

zimmertyzim_35888

02/08/2024, 5:20 PM
The error is:
Cannot bind source content type MyApplication.Models.Login to model type MyApplication.Core.Models.ViewModels.LoginViewModel
My structure looks like this: Login.html
Copy code
csharp
@await Component.InvokeAsync("RenderLogin");
RenderLogin ViewComponent
Copy code
csharp
LoginViewModel model = new(currentPage, new PublishedValueFallback(_serviceContext, _variationContextAccessor));
return View("LoginForm.cshtml", model );
LoginForm.cshtml
Copy code
csharp
@inherits Umbraco.Cms.Web.Common.Views.UmbracoViewPage<LoginViewModel>
@using (Html.BeginUmbracoForm("Login", "Member",  new {}, new {}, FormMethod.Post))
{      
    <input asp-for="@Model.Username" />
    <input asp-for="@Model.Password" />
    <button type="submit">Login</button>
}
MemberController (inherits from SurfaceController)
Copy code
csharp
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult HowAboutThis(LoginViewModel model)
{    
    return CurrentUmbracoPage();
}
LoginViewModel
Copy code
csharp
public class LoginViewModel : Login
{
    ...
    public LoginViewModel(IPublishedContent content,
                           IPublishedValueFallback publishedValueFallback) : base(content, publishedValueFallback)
    {
    }
}
Login
is a content model from the back office, used to output content on LoginForm. Using
<form asp-action="Login" asp-controller="Member" method="POST">
hits the controller, but the model doesn't bind and
CurrentUmbracoPage();
is not available. Removing the model from the Login method works , but I need its content. How should I do this? I guess it's due to
LoginViewModel
inheriting
Login
, but I understand this is okay to extend the view model. Any help would be much appreciated.
it's certainly because I am inheriting from Login. Why is this? If I change don't inherit and use add a property instead it works: LoginViewModel
Copy code
csharp
public Login Login { get; private set; }
  
    public LoginViewModel(IPublishedContent loginContent)
    {
        Login = (Login)loginContent;
    }
ViewComponent
Copy code
csharp
if (_umbracoContextAccessor
            ?.GetRequiredUmbracoContext()
        ?.PublishedRequest
        ?.PublishedContent is Login loginPage)
        {
           loginViewModel = new LoginViewModel(loginPage);
            return View("LoginForm.cshtml", loginViewModel);
        }
...
Is this the correct way / best practice of doing this? or does it not matter?