繁体   English   中英

如何为 html 标题属性设计 InfoHelper

[英]How to design InfoHelper for html title attribute

对于 Asp.net mvc 核心应用程序:在我的一个 dbcontext 表中,我有带有 HelpInfo 的记录(id 作为主键,字符串用于 helpInfo),我想在我的 Z60C05C632A2822A0A843EZ 视图中用作 html 标题属性,例如:

<div title='@I(12)'></div>

其中 12 是 HelpInfo 记录的示例 ID,@I 应该是获取相应 helpInfo 字符串的全局可访问 class 方法。

我尝试实施 King Kings 方法,例如:

自定义视图

public abstract class CustomView<TModel>  : RazorPage<TModel>
{
    protected IInfo Info => Context.RequestServices.GetRequiredService<IInfo>();

    public Task<string> I(int code)
    {
        return Info.GetAsync(code);
    }
}

接口

public interface IInfo
{
    Task<string> GetAsync(int code);
}

服务

public class Info : IInfo
{
    private readonly ApplicationDbContext context;
    public Info(ApplicationDbContext context)
    {
        this.context = context;
    }

    public async Task<string> GetAsync(int code)
    {
        var myRecord = await context.MyRecords.FindAsync(code);
        if (myRecord != null)
        {
            return myRecord.Info;
        }
        return null;
    }
}

在 _ViewImports.cshtml 我添加了@inherits CustomView<TModel>

在视图中我使用了<div title='@(await I(12))'>Test</div>

当我加载视图时,我得到

No service for type '...Models.IInfo' has been registered

任何有助于确定问题的帮助将不胜感激。

据我了解,您似乎想要默认PageRazorPage支持的@Html@Url之类的东西。 这只是基本页面公开的自定义属性。 因此,在您的情况下,您需要自定义视图(用于 mvc)或自定义页面(用于 razor 页面)。 这是用于 MVC 的自定义视图的示例:

public abstract class CustomView<TModel> : RazorPage<TModel>
{              
    //custom members can be declared in here
}

根据您对I的期望用法,它必须是一种方法。 因此,它可以是一些注入到您的基本页面中的服务所公开的方法。 假设界面是这样的:

public interface IInfo {
     string Get(int code);
}

现在您的自定义页面可以像这样实现I方法:

public abstract class CustomView<TModel> : RazorPage<TModel>
{      
    //NOTE: the custom page class does not support constructor injection
    //So we need to get the injected services via the Context like this.
    protected IInfo Info => Context.RequestServices.GetRequiredService<IInfo>();        
    public string I(int code){
       return Info.Get(code);
    }
}

要使用自定义视图,您需要在视图中使用指令@inherits或在_ViewImports.cshtml中使用更好的指令,这样您就不必在任何地方重复@inherits ,如下所示:

@inherits CustomView<TModel>

有时在重建项目之前不会应用基础视图(因此基础成员不可用)。

现在,您可以根据需要使用视图中的I ,如下所示:

<div title="@I(12)"></div>

请注意,我的示例中的I方法返回一个string ,您也可以让它返回一个IHtmlContent (例如: HtmlString )或您需要的任何类型。

注意

从技术上讲,您可以使用任何服务(包括从数据库查询数据的服务),但在这种情况下,请确保查询尽可能快并使用async以获得最佳性能并避免线程饥饿。 以下是从数据库查询的IInfo服务示例:

public interface IInfo {
     Task<string> GetAsync(int code);
}

public class Info : IInfo {
     //inject whatever your Info needs
     //here we just need some DbContext (used in EFCore)
     public Info(InfoDbContext dbContext){
        _infoDbContext = dbContext;
     }
     readonly InfoDbContext _infoDbContext;
     public async Task<string> GetAsync(int code){
         var info = await _infoDbContext....
         return info;
     }
}

I方法也应该是async的:

public Task<string> I(int code){
       return Info.GetAsync(code);
}

我希望您知道如何注册DbContext以在您的代码中使用(这是EFCore的一部分,因此您可能需要先了解更多相关信息)。 现在要使用async方法,您可以像这样在视图中调用它:

<div title="@(await I(12))"></div>

同样,我会尽量避免在这样的助手中查询数据库。 正如我所说,可以在同一个视图中多次调用帮助程序的方法,因此通常我们有快速方法或使用缓存来获取所需的信息。 这与另一个称为caching的功能有关,该功能需要在一个简短的答案中提供更多信息,您可以了解更多信息。

解决方案

在我的 Startup.cs 中,我添加了:

services.AddScoped<IInfo, Info>();

services.AddTransient<IInfo, Info>(); 也确实有效。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM