.NET CORE 从控制器调用 ViewComponent

Posted

技术标签:

【中文标题】.NET CORE 从控制器调用 ViewComponent【英文标题】:.NET CORE Invoke ViewComponent from Controller 【发布时间】:2022-01-14 18:35:15 【问题描述】:

我在从控制器加载 ViewComponent 时遇到问题,我的主视图是 Contact.cshtml,而我的 ViewComponent 是 AddContact.cshtml。 AddContact 是一个带有提交按钮的简单表单,我正在尝试获取它,以便当模型无效时,组件会刷新输入的数据和模型验证消息。

问题是当我在控制器中返回 "ViewComponent("AddContact", newContact)" 时,模型“newContact”无效,它会在一个全新的页面中重新加载 ViewComponent,而不是作为联系人视图中的一部分。是否有一些我遗漏的语法或者这完全需要其他东西?

联系方式.cshtml:

@await Component.InvokeAsync("AddContact", new  addContact = newContactModel )

AddContact.cshtml

@using (Html.BeginForm("AddContact", "Contact", FormMethod.Post))

    ....

    <input id="addContactBtn" type="submit" value="Add" class="btn btn-success">

控制器:

[HttpGet]
public ActionResult AddContact()

      return ViewComponent("AddContact");


[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult AddContact(AddContact_VM newContact)

      if (!ModelState.IsValid)
      
            return ViewComponent("AddContact", newContact);
      

      OperationStatus opStat = granteeRepo.AddContact(newContact);

      return View("Contact");
 

组件:

public class AddContact : ViewComponent

    public IViewComponentResult Invoke(AddContact_VM newContact)
    
         return View("AddContact", newContact);
    


【问题讨论】:

【参考方案1】:

您可以创建一个特定的操作来将请求定向到 ViewCompoent。

这是一个例子,

对于您将被定向的cshtml

&lt;a href="#" data-url='@Url.Action("LoadParametersContent","Home",new key="Home")'&gt;

为了你的HomeContoller.cs

   public IActionResult LoadParametersContent(string key)
   
       return ViewComponent(key);
   

对于HomeViewComponent.cs

    public class HomeViewComponent : ViewComponent
    
        public IViewComponentResult Invoke()
        
            return View("Home");
        
    

之后,您应该在 Shared>Components>Home 下将组件创建为 Home.cshtml

奖金:

我有一个左侧导航栏。使用该导航栏中的锚点,我正在使用视图组件更改右侧的内容。这是实现这一点的 jquery:

$('.nav-link').on('click', function (evt) 
    evt.preventDefault();
    evt.stopPropagation();
    var $detailDiv = $('#content-right'),
        url = $(this).data('url');

    $.get(url, function (data) 
        $detailDiv.html(data);
    );
);

【讨论】:

【参考方案2】:

问题是当我返回 "ViewComponent("AddContact", newContact)" 在具有无效模型“newContact”的控制器中,它重新加载 ViewComponent 在一个全新的页面中,而不是作为部分 联系人视图。

原因是程序先执行了if语句的内容,然后代码返回到AddContact页面。所以它重新加载了 ViewComponent 在一个全新的页面中,而不是作为部分 联系人视图。

您可以尝试将 return ViewComponent("AddContact", newContact); 更改为 return View("Contact"); 在您的 if 控制器中的方法。

我做了一个演示来满足您的要求。 Demo如下。

1.在控制器中,使用Contact动作。

public class ctController : Controller
    
        [HttpGet]
        public IActionResult Contact()
        
            return View();
        
        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Contact(AddContact_VM newContact)
        

            if (!ModelState.IsValid)
            
                return View("Contact");
            

            OperationStatus opStat = granteeRepo.AddContact(newContact);
            return View("Contact");
        

2.在Contact.cshtml中,添加@await Component.InvokeAsync("AddContact")

3.在AddContact.cshtml中,更改表单中的动作名称。

   @model MVCviewcompent.Models.AddContact_VM
    @using (Html.BeginForm("Contact", "ct", FormMethod.Post))
    
        <form asp-controller="ct" asp-action="Contact" method="post">
            <table border="0" cellpadding="2" cellspacing="2">
                <tr>
                    <td>Username</td>
                    <td>
                        <input asp-for="Username" />
                    </td>
                    <td>
                        <span asp-validation-for="Username"></span>
                    </td>
                </tr>
                <tr>
                    <td>Password</td>
                    <td>
                        <input asp-for="Password" type="password" />
                    </td>
                    <td>
                        <span asp-validation-for="Password"></span>
                    </td>
                </tr>
                <tr>
                    <td>Age</td>
                    <td>
                        <input asp-for="Age" />
                    </td>
                    <td>
                        <span asp-validation-for="Age"></span>
                    </td>
                    
                </tr>
    
                <tr>
                    <td>&nbsp;</td>
                    <td>
                        <input type="submit" value="Save" />
                    </td>
                </tr>
            </table>
        </form>

4.In AddContact_VM .cs

public class AddContact_VM
    
        [Required]
        [MinLength(3)]
        [MaxLength(10)]
        public string Username
        
            get;
            set;
        

        [Required]
        [MinLength(3)]
       
        public string Password
        
            get;
            set;
        


        [Required]
        [Range(18, 50)]
        public int Age
        
            get;
            set;
        
   

5.Component 类是你的 AddContact。

结果:

【讨论】:

以上是关于.NET CORE 从控制器调用 ViewComponent的主要内容,如果未能解决你的问题,请参考以下文章

从具有多个参数 net core mvc 的控制器调用另一个 actionresult

使用值从 React 调用 .NET Core 控制器方法

ASP.Net Core 6,SPA,端点 - 我无法从 http get 请求调用控制器

无法在 ASP.Net Core Web api 中启用 CORS

在 ASP.NET Core 中有效地转发来自内部 HttpClient 调用的内容

对于 .net core 6 中的控制器调用,WebApplicationFactory 始终返回 404