Call controller Action Method from Widget

This topic was automatically closed 365 days after the last reply. New replies are no longer allowed.
2 years ago
Hi. I am developing my first plugin, but right now I am stuck trying to call a Controller Action Method from the Widget view.  No error is returned, but submit button does not reach the controller. What am I doing wrong?

The Widget view looks  like this:

@model Nop.Plugin.Widgets.Expressions.Models.PublicInfoModel
@{
    Layout = "";
}
<div class="container" style="margin: 2px; padding: 2px">
  @using (Html.BeginForm("PublicInfo", "WidgetsExpressions", FormMethod.Post,
                         new { enctype = "multipart/form-data", id = "ImgForm", name = "ImgForm", target = "UploadTarget" }))
                            {
                                <input type="hidden" name="productId" value[email protected] />                                
                                <input type="hidden" name="image" id="input_elem" />
                                <button class="btn btn-success" id="submitbutton" type="submit" value="Submit">Save photo</button>                                
                            }
</div>


The Controller Action Method goes:

public class WidgetsExpressionsController : BasePluginController
    {
    public async Task<ActionResult> PublicInfo(string widgetZone, object additionalData)
      {
        FormCollection _form = (FormCollection)additionalData;
        
        //Some code here
        var model = new PublicInfoModel();
        //Some more code...
        return View("~/Plugins/Widgets.Expressions/Views/PublicInfo.cshtl", model);
      }
  }


And the RouteProvider
 endPointRouteBuilder.MapControllerRoute("Plugin.Widgets.Expressions.WidgetsExpressions.PublicInfo", "Plugins/WidgetsExpressions/PublicInfo",
                new { controller = "WidgetsExpressions", action = "PublicInfo" });



Thanks
2 years ago
If you're using a Form to get there, you may need a [HttpPost] attribute on your Action method.   Also,  use the browser dev tools to be sure a request is being made.   ​However...

Typically the PublicInfo method is used to deliver the widget 'content'.  You may want to us another method for your "processing", and also consider using Ajax.
2 years ago
Thank you so much New York for your suggestions. Actually, HttpPost attribute was yet there, I just forgot to include it in this Post. To implement your suggestion, I created a new controller (Photo) with an ActionResult method (TakePhoto) and added the ajax code to the view (PublicInfo.cshtml):

@model Nop.Plugin.Widgets.Expressions.Models.PublicInfoModel
@{
    Layout = "";
//Some Html here...
                        <div class="col-sm-6">                          
                            <form id="AjaxForm">
                                <input type="hidden" id="productId" value[email protected] />
                                <input type="hidden" id="expressionName" value[email protected] />
                                <input type="hidden" id="role" value[email protected] />
                                <input type="hidden" id="counter" value[email protected] />
                                <input type="hidden" id="input_elem" name="image" />
                                <button class="btn btn-success" id="submitbutton" type="submit" value="Submit">Save photo</button>
                            </form>                        
</div>
                  
<script language="javaScript">
    (function () {      
        //=====================================      
    $(document).ready(function () {
        $("#AjaxForm").submit(function (e) {
            e.preventDefault();          
            // Deshabilitamos el botón de Submit
            $("#SubmitBtn").prop("disabled", true);

            var data = canvas.toDataURL('image/png');

                $.ajax({
                    url: "@Url.Action("TakePhoto", "Photo")", // Url
                    data: {
                        // Datos / Parámetros
                            ProductId: $("#productId").val(),
                            ExpressionName: $("#expressionName").val(),
                            Role: $("#role").val(),
                            Counter: $("#counter").val(),
                            Photo: $("#input_elem").val(data)
                    },
                    type: "post"  // Verbo HTTP
                })
</script>


And changed RouteProvider:

namespace Nop.Plugin.Widgets.Expressions
{
    public partial class RouteProvider : IRouteProvider
    {
        public void RegisterRoutes(IEndpointRouteBuilder endPointRouteBuilder)
        {          
            endPointRouteBuilder.MapControllerRoute("Plugin.Widgets.Expressions.WidgetsExpressions.Configure", "Plugins/WidgetsExpressions/Configure",
                new { controller = "WidgetsExpressions", action = "Configure" });

            endPointRouteBuilder.MapControllerRoute("Plugin.Widgets.Expressions.BookExpressions.AddExpressiontoBook", "Plugins/BookExpressions/AddExpressiontoBook",
                new { controller = "BookExpressions", action = "AddExpressiontoBook" });

            //This is my public endPoint
            endPointRouteBuilder.MapControllerRoute("Plugin.Widgets.Expressions.Photo.TakePhoto", "Plugins/Photo/TakePhoto",
                new { controller = "Photo", action = "TakePhoto" });

        }
        public int Priority => -1;
    }
}


However, it is not working. Url route cannot be found. As controllers and the view component are within a dll file, I guess a reference has to be added to the assembly controller with Microsoft.AspNetCore.Mvc.ApplicationParts, as mentioned here. But the problem is that I don't know how to do that. Can anyone please explain how to do this in NopCommerce 3.1 ?
Also, I am not sure how the Url Route pattern goes in RouteProvider. I have tried with: "Photo/TakePhoto" "Plugins/Photo/TakePhoto", "Plugins/Widgets.Expressions/Photo/TakePhoto",with no luck. An explanation will be appreciated.

Thanks in advance.
Dumar
2 years ago
Well, according to this, it seems I am going in the right direction. I tried to add my plugin controller in the nop.web/statup.cs class this way (just as it is done here:
 // Requires using System.Reflection;
            var assembly = typeof(PhotoController).GetTypeInfo().Assembly;
            services.AddMvc()
                .AddApplicationPart(assembly)
                .SetCompatibilityVersion(CompatibilityVersion.Version_3_0);


But I am getting a CS0246 error (The type or namespace name 'type/namespace' could not be found (are you missing a using directive or an assembly reference?)) by the typeof operator.
What should I do to solve this?  Or, I am taking it the wrong way, how can be this issue addressed ?
This topic was automatically closed 365 days after the last reply. New replies are no longer allowed.