使用 Ninject 将类注入 IModelBinder



我有以下自定义模型绑定器:

public class AllowAndSanitizeHtmlBinder : IModelBinder
{
// initialize HtmlSanitizer (I want this to be injected)
private HtmlSanitizer _htmlSanitizer = new HtmlSanitizer();
sanitizer.PostProcessNode += (s, e) =>  
(e.Node as IHtmlAnchorElement)?.SetAttribute("rel", "nofollow");
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
var request = controllerContext.HttpContext.Request;
var name = bindingContext.ModelName;
// get the unvalidated user input
var unsanitizedMessageHtmlString = request.Unvalidated[name]; 
// removed script or any XSS threat from user input
return _htmlSanitizer.Sanitize(unsanitizedMessageHtmlString); 
}
}

我对这段代码的问题是我正在模型绑定器类中执行HtmlSanitizer的所有初始化(这违反了 SRP)。是否可以将HtmlSanitizer注入上述粘合剂中?我正在使用Ninject。

我已经看到了这个问题:公认的答案表明模型活页夹不应该依赖于任何服务,我不确定这里的情况是否如此......我认为 DI 会简化我的代码。

您需要自定义IModelBinderProvider来实现此目的。

public class AllowAndSanitizeHtmlBinderProvider : IModelBinderProvider
{
public HtmlSanitizer Sanitizer{get;}
public AllowAndSanitizeHtmlBinderProvider(HtmlSanitizer sanitizer)
{
Sanitizer = sanitizer;
}
public IModelBinder GetBinder(Type modelType)
{
if(modelType==typeof(string)) // I assume it's string
return new AllowAndSanitizeHtmlBinder (Sanitizer);
return null;
}
}
public class AllowAndSanitizeHtmlBinder : IModelBinder
{
private HtmlSanitizer _htmlSanitizer;
public AllowAndSanitizeHtmlBinder(HtmlSanitizer sanitizer)
{
_htmlSanitizer = sanitizer;
}

public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
var request = controllerContext.HttpContext.Request;
var name = bindingContext.ModelName;
// get the unvalidated user input
var unsanitizedMessageHtmlString = request.Unvalidated[name]; 
// removed script or any XSS threat from user input
return _htmlSanitizer.Sanitize(unsanitizedMessageHtmlString); 
}
}

然后在你的 Ninject 配置

kernel.Bind<IModelBinderProvider>().To<AllowAndSanitizeHtmlBinderProvider >();
kernel.Bind<HtmlSanitizer>().ToMethod(ctx => { 
var sanitizer = new HtmlSanitizer();
sanitizer.PostProcessNode += (s, e) =>  
(e.Node as IHtmlAnchorElement)?.SetAttribute("rel", "nofollow");
return sanitizer;
});

更好的方法是为AllowAndSanitizeHtmlBinder定义一个工厂,该工厂将保持对HtmlSanitizer的依赖性。然后,提供程序将仅接收工厂作为依赖项。这将掩盖对提供程序HtmlSanitizer的依赖关系。

此外,它还允许将HtmlSanitizer隐藏在接口后面,并让所有非Ninject代码解决此接口。这将允许对代码的其他部分隐藏此技术依赖关系。

最新更新