博客 (8)

有一个项目,在 VS2022 中正常打开,在 VS2019 中无法加载项目,项目目标框架是 .NET Standard 2.0。报错内容:

error: 无法打开项目文件。 .NET SDK 的版本 7.0.306 至少需要 MSBuild 的 17.4.0 版本。当前可用的 MSBuild 版本为 16.11.2.50704。请将在 global.json 中指定的 .NET SDK 更改为需要当前可用的 MSBuild 版本的旧版本。

解决方法:

运行 Visual Studio Installer,选择 Visual Studio 2019 进行修改,切换到“单个组件”,勾选“.NET SDK (out of support)”,会联动勾选“.NET 5.0 Runtime (Out of support)”与“.NET Core 3.1 Runtime (Out of support)”。

QQ截图20230728135007.png

xoyozo 10 个月前
5,479

新版本 SDK 已解决这个问题


image.png

升级到 .NET 7 后,Senparc.Weixin 6.15.7 正常,6.15.8.1-6.15.8.3 无法正常启动,行

builder.Services.AddSenparcWeixinServices(builder.Configuration);

报错:

System.NullReferenceException:“Object reference not set to an instance of an object.”

临时解决方法,改为:

builder.Services.AddSenparcWeixinServices(builder.Configuration, delegate { });



a
转自 adaxiong 1 年前
1,108

本文使用 ASP.NET 6 版本 Senparc.Weixin.Sample.MP 示例项目改造。


第一步 注册多公众号

方法一:打开 appsettings.json 文件,在 SenparcWeixinSetting 节点内添加数组节点 Items,该对象类型同 SenparcWeixinSetting。

//Senparc.Weixin SDK 设置
"SenparcWeixinSetting": {
  "IsDebug": true,
  "Token": "",
  "EncodingAESKey": "",
  "WeixinAppId": "",
  "WeixinAppSecret": "",
  "Items": [
    {
      "IsDebug": true,
      "Token": "a",
      "EncodingAESKey": "a",
      "WeixinAppId": "a",
      "WeixinAppSecret": "a"
    },
    {
      "IsDebug": true,
      "Token": "b",
      "EncodingAESKey": "b",
      "WeixinAppId": "b",
      "WeixinAppSecret": "b"
    }
  ]
}

方法二:修改 Program.cs 文件,在 UseSenparcWeixin 方法中注册多个公众号信息。

var registerService = app.UseSenparcWeixin(app.Environment,
    null /* 不为 null 则覆盖 appsettings  中的 SenparcSetting 配置*/,
    null /* 不为 null 则覆盖 appsettings  中的 SenparcWeixinSetting 配置*/,
    register => { /* CO2NET 全局配置 */ },
    (register, weixinSetting) =>
    {
        //注册公众号信息(可以执行多次,注册多个公众号)
        //register.RegisterMpAccount(weixinSetting, "【盛派网络小助手】公众号");
        foreach (var mp in 从数据库或配置文件中获取的公众号列表)
        {
            register.RegisterMpAccount(new SenparcWeixinSetting
            {
                //IsDebug = true,
                WeixinAppId = mp.AppId,
                WeixinAppSecret = mp.AppSecret,
                Token = mp.Token,
                EncodingAESKey = mp.EncodingAeskey,
            }, mp.Name);
        }
    });

完成后,我们可以从 Config.SenparcWeixinSetting.Items 获取这些信息。


第二步 接入验证与消息处理

打开 WeixinController 控制器,将构造函数改写为:

public WeixinController(IHttpContextAccessor httpContextAccessor)
{
    AppId = httpContextAccessor.HttpContext!.Request.Query["appId"];
    var MpSetting = Services.MPService.MpSettingByAppId(AppId);
    Token = MpSetting.Token;
    EncodingAESKey = MpSetting.EncodingAESKey;
}

示例中 Services.MPService.MpSettingByAppId() 方法实现从 Config.SenparcWeixinSetting.Items 返回指定 appId 的公众号信息。

为使 IHttpContextAccessor 注入生效,打开 Program.cs,在行

builder.Services.AddControllersWithViews();

下方插入

builder.Services.AddHttpContextAccessor();

这样,我们就可以在构造函数中直接获取地址栏中的 appId 参数,找到对应的公众号进行消息处理。


第三步 消息自动回复中的 AppId

打开 CustomMessageHandler.cs,将 

private string appId = Config.SenparcWeixinSetting.MpSetting.WeixinAppId;
private string appSecret = Config.SenparcWeixinSetting.MpSetting.WeixinAppSecret;

替换为:

private string appId = null!;
private string appSecret = null!;

并在构造函数中插入

appId = postModel.AppId;
appSecret = Services.MPService.MpSettingByAppId(postModel.AppId).WeixinAppSecret;

这样,本页中使用的 appId / appSecret 会从 postModel 中获取,而非默认公众号。postModel 已在 WeixinController 中赋值当前的 appId。

改造后,我们可以在 OnTextRequestAsync() 等处理消息的方法中可以判断 appId 来处理不同的消息。


第四步 其它功能和接口

其它功能和接口均可用指定的 AppId 和对应的 AppSecret 进行调用。

xoyozo 2 年前
1,870

当 ASP.NET 发布一个新的小版本更新时(以 .NET 5.0.10 为例),生产环境服务器端可以直接下载安装 .NET 5.0.10 来自动替换 .NET 5.0.9。

倘若这时直接使用 VS 将 nuget 中版本为 5.0.9 的组件更新到 5.0.10 发布到服务器上的话,可能会发生错误:

HTTP Error 500.30 - ASP.NET Core app failed to start

这里我们可以在 nuget 回滚相关组件的版本至 5.0.9,等 VS 发现新的版本更新时,更新 VS 开发工具后,再更新 nuget 组件并进行发布即可。

着急的小伙伴可以直接前往 Microsoft .NET 网站下载安装包含 Runtime 5.0.10 的 SDK:

image.png

该情况同样发生在 ASP.NET Core 3.1 等大版本上。

若仍未生效,请重启服务器

----------------

后注:安装完成后重启服务器可避免以上烦恼!

xoyozo 3 年前
1,464

* 若无特殊注明,本文中的“手机”包含平板电脑


判断网页是否在移动设备中打开


Web Form:

public static bool IsMobileDevice
{
    get
    {
        return (HttpContext.Current.Request.Browser?.IsMobileDevice ?? false)
            || (HttpContext.Current.Request.UserAgent?.Contains("Mobile") ?? false);
    }
}


ASP.NET Core:

好像还没有找到,可能是因为随着响应式布局的流行以及电脑和手机之间的界线越来越不明朗,取消了这个判断?


判断网页是否在微信浏览器中打开(宽松)


Web Form:

public bool IsInWechat
{
    get
    {
        return HttpContext.Current.Request.UserAgent?.Contains("MicroMessenger") ?? false;
    }
}


ASP.NET Core:

需注入 IHttpContextAccessor

public bool IsInWechat
{
    get
    {
        string ua = httpContextAccessor.HttpContext.Request.Headers[HeaderNames.UserAgent];
        return ua?.Contains("MicroMessenger") ?? false;
    }
}


判断网页是否在微信浏览器中打开(严谨)


使用 JS-SDK 网页授权来判断




xoyozo 4 年前
2,883

之前已经介绍了百度编辑器在 ASP.NET 环境下的配置,本文继续补充改进其将图片等附件上传到阿里云 OSS。

首先从阿里云控制台下载相关 SDK,并阅读相关的 API 文档。链接:https://promotion.aliyun.com/ntms/act/ossdoclist.html


改造上传代码


打开文件 UploadHandler.cs,在 Process() 方法中找到:

File.WriteAllBytes(localPath, uploadFileBytes);

在其下方插入代码:

client.PutObject(bucketName, "upload/ueditor/" + savePath, localPath);

实现图标按钮上传和 HTML5 拖放上传。

PutObject() 的第 2 个参数是 OSS 中的图片路径,第 3 个参数是图片在网站目录下的磁盘路径。


打开文件 CrawlerHandler.cs,在 Fetch() 方法中找到:

File.WriteAllBytes(savePath, bytes);

在其下方插入代码:

client.PutObject(bucketName, "upload/ueditor/" + ServerUrl, savePath);

实现粘贴板图片上传。

同样注意两个参数变量。


修改路径前缀


上传成功后,编辑器会拼装路径到 HTML 代码中,这个前缀是在 config.json 文件中配置的,具体找到以 UrlPrefix 结尾的属性,如 imageUrlPrefix,进行相应的修改即可:

"imageUrlPrefix": "//oss.xoyozo.net/upload/ueditor/", /* 图片访问路径前缀 */

路径以“//”开头能更好地兼容 https。

xoyozo 5 年前
5,424
  1. 下载 Senparc 官方 Sample


  2. 打开:\WeiXinMPSDK-master\src\Senparc.Weixin.MP.Sample\Senparc.Weixin.MP.Sample.sln


  3. 工具 - NuGet 包管理器 - 管理解决方案的 NuGet 程序包 - 更新

    选择所有的包(Microsoft.Net.Http 无法更新,暂不勾选),更新

    Microsoft.Net.Http 是个老顽固,无法更新也无法卸载,原因是它的语言包 Microsoft.Net.Http.zh-Hans 无法安装。我们切换到“已安装”选项卡,搜索“Microsoft.Net.Http”,选中 Microsoft.Net.Http.zh-Hans 并卸载它,现在我们可以更新 Microsoft.Net.Http 了。


  4. 【可能】运行报错:

    “/”应用程序中的服务器错误。

    配置错误

    说明: 在处理向该请求提供服务所需的配置文件时出错。请检查下面的特定错误详细信息并适当地修改配置文件。 

    分析器错误消息: 创建 system.web.webPages.razor/host 的配置节处理程序时出错: 未能加载文件或程序集“System.Web.WebPages.Razor, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35”或它的某一个依赖项。找到的程序集清单定义与程序集引用不匹配。 (异常来自 HRESULT:0x80131040)

    源错误: 

    行 4:    <configSections>
    行 5:      <sectionGroup name="system.web.webPages.razor" type="System.Web.WebPages.Razor.Configuration.RazorWebSectionGroup, System.Web.WebPages.Razor, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
    行 6:        <section name="host" type="System.Web.WebPages.Razor.Configuration.HostSection, System.Web.WebPages.Razor, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" />
    行 7:        <section name="pages" type="System.Web.WebPages.Razor.Configuration.RazorPagesSection, System.Web.WebPages.Razor, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" />
    行 8:      </sectionGroup>


    源文件: E:\WeiXinMPSDK-master\src\Senparc.Weixin.MP.Sample\Senparc.Weixin.MP.Sample\views\web.config    行: 


    展开 Senparc.Weixin.MP.Sample 引用,查看 System.Web.Razor 的属性,复制版本号。打开 \views\web.config,修改 System.Web.WebPages.Razor 的 Version(有 3 处)。


  5. 对于小型开发项目来说,我习惯将所有代码放在同一个项目(Project)中来,所以做了以下处理:(盛派官方分离这些代码是为了同时供 MVC 和 WebForms 重用)

    在 Senparc.Weixin.MP.Sample 中添加文件夹 CommonService,将 Senparc.Weixin.MP.Sample.CommonService 项目中的文件夹和文件(.config 除外)拖到 CommonService 文件夹中。

    卸载 Senparc.Weixin.MP.Sample.CommonService 项目并删除引用。


  6. 在解决方案的 Libraries 文件夹中,我们看到 Sample 项目了以下功能模块,这些就是 Senparc.Weixin 的源代码,如果不需要修改,可以卸载它们改为使用从 NuGet 获取,以便随时更新到最新版本:

    Senparc.WebSocket

    Senparc.Weixin

    Senparc.Weixin.MP

    Senparc.Weixin.MP.MvcExtension NuGet 中对应的包名为:Senparc.Weixin.MP.MVC

    Senparc.Weixin.Open

    Senparc.Weixin.Work

    Senparc.Weixin.WxOpen

    Senparc.Weixin.Cache.Memcached

    Senparc.Weixin.Cache.Redis

    卸载这些项目,并在 NuGet 中安装这些模块(搜索“Senparc.Weixin”第一页都在了,认准作者 Jeffrey Su)

    单元测试项目中的引用也按需更换,当然也可以卸载这些单元测试项目(视情况保留 Senparc.Weixin.MP.Sample.Tests) 。


  7. 【可能】运行报错


    HTTP Error 500.19 - Internal Server Error

    无法访问请求的页面,因为该页的相关配置数据无效。

    配置源:

    134:     </sessionState>

    135:   <sessionState customProvider="Memcached" mode="Custom">

    136: <providers>


    可以在 Global.asax 的 RegisterWeixinCache() 中修改 Memcached 配置。

    或者打开 Web.config,找到 Memcached 所在的 sessionState 标签,注释掉,这样程序自动使用上方的 InProc(应用进程内)。

    如果开启了 ASP.NET State Service 服务,那么建议改用 StateServer,与 Custom 一样需要序列化,方便日后改用 Memcached 或 Redis。


  8. 再次更新 NuGet,否则会提示无法加载 Enyim.Caching 的错误(报错行:MemcachedObjectCacheStrategy.RegisterServerList(memcachedConfig);)。


  9. 接下来,进入微信公众平台,在左侧 开发 - 基本配置 中设置相关参数(填写“服务器地址(URL)”如“https://weixin.xoyozo.net/weixin/”),打开 Sample 项目中的 Web.config,配置我们的公众号参数。


  10. 将项目发布到服务器上,尝试向公众号发送消息吧。


  11. 单元测试

    设置单元测试中的公众号配置项:打开 Senparc.Weixin.MP.Test/CommonAPIs/CommonApiTest.cs,在 AppConfig 方法中可以看到支持两种配置方式,在 Senparc.Weixin.MP.Test/Config/test.config 配置文件中配置,或直接在 CommonApiTest.cs 文件中配置,前者格式如下,后者建议只在个人测试项目中使用。

    <Config>
      <AppId>YourAppId</AppId>
      <Secret>YourSecret</Secret>
      <MchId>YourMchId</MchId>
      <TenPayKey>YourTenPayKey</TenPayKey>
      <TenPayCertPath>YourTenPayCertPath</TenPayCertPath>
      <!-- 小程序 -->
      <WxOpenAppId>YourOpenAppId</WxOpenAppId>
      <WxOpenSecret>YourWxOpenSecret</WxOpenSecret>
    </Config>

    另外,将 _testOpenId 值改为自己的微信号在本公众号上的 openid。


  12. 微信网页授权(OAuth2)

    打开 OAuth2Controller 控制器,将“Index”Action 中的盛派的网址(有 2 处)改成:

    Request.Url.Scheme + "://" + Request.Url.Authority + "/Oauth2/……


  13. 未完待续……

xoyozo 7 年前
5,490