C# 带回发的MVC组件

C# 带回发的MVC组件,c#,asp.net,asp.net-mvc,components,child-actions,C#,Asp.net,Asp.net Mvc,Components,Child Actions,我正在尝试构建一组MVC组件,这些组件可以轻松地在各种设置下重用。它们被构建并用作子操作,因为我需要它们能够在不知道承载它们的视图的其他内容的情况下对自己进行部分回发 我面临一个问题,即在不通过客户端传递参数的情况下,在何处存储它们的参数(出于安全原因,我不想构建视图状态之类的东西),并使它们可用于部分回发 下面是一个简化的示例(并不是说代码可能无法编译,因为我将语法简化为纯MVC): 查看代码(组件使用): 提要视图代码: @using (Ajax.BeginForm("Default", "

我正在尝试构建一组MVC组件,这些组件可以轻松地在各种设置下重用。它们被构建并用作子操作,因为我需要它们能够在不知道承载它们的视图的其他内容的情况下对自己进行部分回发

我面临一个问题,即在不通过客户端传递参数的情况下,在何处存储它们的参数(出于安全原因,我不想构建视图状态之类的东西),并使它们可用于部分回发

下面是一个简化的示例(并不是说代码可能无法编译,因为我将语法简化为纯MVC):

查看代码(组件使用):

提要视图代码:

@using (Ajax.BeginForm("Default", "FacebookFeed", new AjaxOptions { HttpMethod = "POST", InsertionMode = InsertionMode.ReplaceWith }))
{
    // Form code

    <input type="submit" value="Refresh" />
}
@using (Ajax.BeginForm("Default", "FacebookFeed", new AjaxOptions { HttpMethod = "POST", InsertionMode = InsertionMode.ReplaceWith }, new { settingsKey = Model.SettingsKey }))
{
   ...
}
来自用户的额外代码:

[ComponentSettings]
public class HomePageFBFeed : FacebookFeedSettings
{
    public HomePageFBFeed()
    {
        AppKey = "XYZ";
        AppSecret = "123";
        PageSize = 10;
    }
}
修改的控制器代码:

public class FacebookFeedController {
   public ActionResult Default(FacebookFeedSettings settings)
   {
      // Action code using settings

      return PartialView(model);
   }
}
public ActionResult Default(string settingsKey)
{
   FacebookFeedSettings settings = ComponentSettings.GetSettings(settingsKey);

   // Action code using settings

   return PartialView(model);
}
修改的视图代码:

@using (Ajax.BeginForm("Default", "FacebookFeed", new AjaxOptions { HttpMethod = "POST", InsertionMode = InsertionMode.ReplaceWith }))
{
    // Form code

    <input type="submit" value="Refresh" />
}
@using (Ajax.BeginForm("Default", "FacebookFeed", new AjaxOptions { HttpMethod = "POST", InsertionMode = InsertionMode.ReplaceWith }, new { settingsKey = Model.SettingsKey }))
{
   ...
}
因此,在这种情况下,我只向客户端传递该配置的一些唯一ID,这很好,但与第一个配置相比,它的用户体验很差,因为它需要在组件所在的视图之外进行管理

在这种情况下,我也不能像第一个代码部分所示使用内联模板,因为在这种情况下,设置是在视图范围之外构建的

请注意,我还需要它来处理应用程序重启和跨流程边界(在云中),所以我不能依赖于在第一次加载视图时将配置存储在服务器端

在ASP.NET4.6/MVC5中有没有更好的方法/最佳实践


如果不是,在ASP.NET 5/MVC 6中是否可能?

马丁,我知道你说过你不想创建视图状态,但考虑到MVC的断开连接模式(你不想使用服务器端会话,也因为它不可扩展),你是否愿意传输加密的设置字符串

视图中的类似内容:

@using (Ajax.BeginForm("Default", "FacebookFeed", new AjaxOptions { HttpMethod = "POST", InsertionMode = InsertionMode.ReplaceWith }))
{
    @Html.AntiForgeryToken()
    <input type="hidden" name="Settings" value="@Model.ToEncryptedString()" />
    <input type="submit" value="Refresh" />
}
FromEncryptedString()的作用方向正好相反:

  • 从基64转换为字节[]
  • 解密字节数组
  • 反序列化到FacebookFeedSettings对象实例
  • 基本上,这个加密字符串的工作原理或多或少类似于防伪令牌。 为了使其更加优雅,我想您也可以在属性级别移动设置验证,并使用自定义属性标记您的操作:

    [HttpPost, ValidateAntiForgeryToken, FacebookFeedSettings]
    public ActionResult Default(/* No need to capture settings here */)
    
    FacebookFeedSettingsAttribute将从请求和生成中获取设置参数,并验证FacebookFeedSettings对象实例。 在我的尝试中,我没有尝试走这么远,我把它留给你去练习:-)


    你觉得怎么样?

    Martin,我知道你说过你不想创建视图状态,但是考虑到MVC的断开连接模式(你不想使用服务器端会话,也因为它不可扩展),你会愿意传输加密的设置字符串吗

    视图中的类似内容:

    @using (Ajax.BeginForm("Default", "FacebookFeed", new AjaxOptions { HttpMethod = "POST", InsertionMode = InsertionMode.ReplaceWith }))
    {
        @Html.AntiForgeryToken()
        <input type="hidden" name="Settings" value="@Model.ToEncryptedString()" />
        <input type="submit" value="Refresh" />
    }
    
    FromEncryptedString()的作用方向正好相反:

  • 从基64转换为字节[]
  • 解密字节数组
  • 反序列化到FacebookFeedSettings对象实例
  • 基本上,这个加密字符串的工作原理或多或少类似于防伪令牌。 为了使其更加优雅,我想您也可以在属性级别移动设置验证,并使用自定义属性标记您的操作:

    [HttpPost, ValidateAntiForgeryToken, FacebookFeedSettings]
    public ActionResult Default(/* No need to capture settings here */)
    
    FacebookFeedSettingsAttribute将从请求和生成中获取设置参数,并验证FacebookFeedSettings对象实例。 在我的尝试中,我没有尝试走这么远,我把它留给你去练习:-)


    你怎么看?

    我理解并且同意,问题是你希望在无状态技术中保留某种形式的状态

    好消息是MVC6似乎已经解决了您的问题。首先,子操作不再存在,取而代之的是视图组件。 视图组件由C#类和Razor视图组成,并且不依赖于控制器,这简化了可重用性

    我还没有直接的经验,但从我所阅读的有关MVC6的内容,特别是查看组件的内容来看,它们是自包含的,因此基本上可以管理组件本身的状态。参数不会从视图通过HTTP传递,因为您实际上调用了组件服务器端(没有从客户端返回)

    此外,视图组件不参与控制器生命周期,但您仍然可以访问ViewBag和ViewData(与控制器共享)。Lasty与控制器一样,视图组件也参与依赖项注入,因此您需要的任何其他信息都可以简单地注入到视图组件中


    这应该对您有效,但您需要等待MVC 6:-)

    我理解并且同意,问题是您希望在无状态技术中保留某种形式的状态

    好消息是MVC6似乎已经解决了您的问题。首先,子操作不再存在,取而代之的是视图组件。 视图组件由C#类和Razor视图组成,并且不依赖于控制器,这简化了可重用性

    我还没有直接的经验,但从我所阅读的有关MVC6的内容,特别是查看组件的内容来看,它们是自包含的,因此基本上可以管理组件本身的状态。参数不会从视图通过HTTP传递,因为您实际上调用了组件服务器端(没有从客户端返回)

    此外,视图组件不参与控制器生命周期,但您仍然可以访问ViewBag和ViewData(与控制器共享)。Lasty与控制器一样,视图组件也参与依赖项注入,因此您需要的任何其他信息都可以简单地注入到视图组件中


    这应该适合您,但您需要等待MVC 6:-)

    谢谢您的回答。我想避免这种情况,这基本上就是我所说的避免ViewState的意思。我简化了案例,但设置可能会继续