1

Currently we're using view rendering for login form but as per new requirement we need to change to Controller rendering to perform some logic in backend during submission. This looks like as given below. We're using Glass mapper so given Sitecore field( Header,UsernameLabel,LoginLabel ) render the field value directly from Sitecore on form load.

login.cshtml

@model ILogin
<form id="loginForm" name="loginForm" action="/someurl" method="POST">
<h2>@Html.Glass().Editable(m => m.Header)</h2>
...
<label>@Html.Glass().Editable(m => m.UsernameLabel)</label>
...
<button type="submit">@Html.Glass().Editable(m => m.LoginLabel)</button>
</form>

We created new Controller Rendering and Login GET and POST Action method in Controller

GET

public ActionResult Login()
{
 var model = _mvcContext.SitecoreService.GetItem<ILogin>(_mvcContext.DataSourceItem);
 return View("~/public/Views/login.cshtml", model);
}

POST

[HttpPost]
public ActionResult Login(ILogin model)
{
}

During GET operation,login form is loading properly but getting below error during submission:

Cannot create an instance of an interface.
Description: An unhandled exception occurred.
Exception Details: System.MissingMethodException: Cannot create an instance of an interface.
[MissingMethodException: Cannot create an instance of an interface. Object type 'Models.ILogin'.]
   System.Web.Mvc.DefaultModelBinder.CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType)

Then while searching online we found that create a new class and implement interface. That means in GET method we need to get data source item, fetch values from Sitecore, fill values in class properties and return new class model. In POST method, replace ILogin with new class. This seems alternate options but Is there any other way we can handle submission instead of adding new class?

3
  • You can pass the ID of the datasource back in Post and retrieve the values on server side again. No need to pass a full Login object
    – Marek Musielak
    Commented May 19, 2023 at 6:16
  • I want to understand here that you also need the form submit context where you will get the user input values in post method. right? Commented May 19, 2023 at 12:33
  • Correct. I'm planning to access those values in backend by Request.Form["userid"]
    – Sukhjeevan
    Commented May 19, 2023 at 13:09

1 Answer 1

0

The MVC model binder needs to create an instance of every object in the postback model in order to bind the form values to it. If the postback model contains a property of an interface type (instead of a concrete type) then the model binder won’t be able to create an instance of that property – because it won’t know which concrete type to create, hence the error.

I agree with @Marek that you can the ItemId and retrieve/process information like this using Html.BeginRouteForm.

View:

@using (Html.BeginRouteForm(Sitecore.Mvc.Configuration.MvcSettings.SitecoreRouteName, FormMethod.Post))
{
    @Html.Sitecore().FormHandler("LoginController", "Login")
    @Html.Hidden("itemId", @viewModel.Id.ToString())
}

Controller:

[HttpPost]
public ActionResult Login(string itemId)
    {
         var Item = Sitecore.Context.Database.GetItem(new ID(itemId));
         if (Item == null)
         {
             //// TODO: Put the code for the error handling
         }
 
        ////TODO: Perform your custom business logic here.
        
         return View();
     }

Hope it helps!

3
  • Yeah this helps. Actually I found that even I don't need to create Controller Rendering and GET action method. I just wrote [HttpPost] in Controller, code in .cshtml file as you explained and hit the Submit button. I was able to get itemId and user input values by Request.Form["userid"] approach. I'm not sure if it's good to go without Controller Rendering.
    – Sukhjeevan
    Commented May 19, 2023 at 18:48
  • If you need to implement custom business logic then go with controller rendering else view rendering. Commented May 20, 2023 at 1:44
  • I'm glad to hear that, If this answer or any other one solved your issue or helps to resolve it, please mark it as accepted for the community. For more details sitecore.stackexchange.com/help/someone-answers Commented May 21, 2023 at 16:39

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.