高级Blazor:从Edge共享程序集和调试

目录

使用Razor

服务你的Blazor

调试客户端(Edge版)


Blazor WebAssembly引起了人们极大的兴趣。开发人员最终能够使用他们选择的语言(例如C#)构建基于浏览器的单页应用程序(SPA)。在撰写本文时,Blazor WebAssembly处于预览状态。该团队计划在20205月发布该版本,以致力于增加功能并改善开发人员体验。Blazor WebAssembly项目的最大挑战之一是缺乏集成调试。

这里正在缓慢演变的调试经验。同时,您可以遵循一些简单的步骤和做法来使生活更简单。

使用Razor

我遵循最低公分母的发展理念。我将可以在最广泛的范围内共享的东西拉到单独的组件中,并尝试使逻辑与框架实现脱钩。例如,我更喜欢使用Blazor MVVM模式,而不是将逻辑直接直接嵌入Razor组件内部。这使我可以使用BlazorASP.NET MVCWPF甚至Xamarin(移动)项目之间共享的类库。下一个是视图,使用Razor类库,用户界面(UI)也可以共享!

与其直接在Blazor项目中构建Razor组件,不如考虑将它们放在Razor类库中。Razor类库不限于本地组件;您还可以嵌入JavaScript,图像和其他共享资源。此博客文章中的代码全部包含在示例应用程序中:

 JeremyLikness / AdvancedBlazor

首先,我创建了一个Razor类库并将其命名为BlazorApp.Shared。项目模板会生成一些默认文件,这些文件会被一些自定义组件覆盖。默认情况下,将嵌入一个JavaScript文件,该文件从提示中返回文本。

window.exampleJsFunctions = {
   showPrompt: function (message) {
      return prompt(message, 'Type anything here');
   }
};

名为ExampleJsInterop的类提供了对JavaScript调用的包装。

扫描二维码关注公众号,回复: 8739147 查看本文章
public class ExampleJsInterop
{
   public static ValueTask<string> Prompt(IJSRuntime jsRuntime, string message)
   {
      // Implemented in exampleJsInterop.js
      return jsRuntime.InvokeAsync<string>(
         "exampleJsFunctions.showPrompt",
         message);
   }
}

为了使在项目中的任何地方都可以轻松使用JavaScript互操作性,我向以下_Imports.razor代码添加了using语句:

@using Microsoft.JSInterop

接下来,我创建了一个名为Prompter.razor的组件,该组件在单击按钮时显示提示并更新一些文本。模板如下所示:

<div class="my-component">
This Blazor component is defined in the <strong>BlazorApp.Shared</strong> package.
</div>
<button @onclick="GetText">Enter Text</button>
<p>Prompt text: @Text</p>

后面的代码使用JavaScript提示来检索文本并更新类的属性。

public string Text { get; set; } = "Click the button to change this.";
public async void GetText()
{
   Text = await ExampleJsInterop.Prompt(JsRuntime, "Enter your text:");
   StateHasChanged();
}

在此示例中,我使用模板生成的代码。与使用静态方法相比,更好的实现是为接口提供方法签名,并将实现注册为Startup类中的单例,然后在需要时将其注入。这将使单元测试更容易编写。

这个简单的组件的目的是说明如何编写自定义JavaScript并将其运送到共享库中。我创建了另一个名为ShowHost的组件,该组件显示的日期和托管(OS)平台,如System.Environment.OSVersion。您将在此博客文章的后面看到原因。模板:

<h3>Your environment is: @OS (last refreshed at: @Refresh)</h3>
<button @οnclick="DoRefresh">Refresh Environment</button>

后面的代码:

public string OS { get; set;} = "Not Set";
public string Refresh { get; set; } = "never";
protected override void OnInitialized()
{
   DoRefresh();
}
public void DoRefresh()
{
   OS = Environment.OSVersion.VersionString;
   Refresh = DateTime.Now.ToString();
}

最后,我添加了一个Wrapper包装其他组件的控件,因此只需要在Blazor项目中删除一个组件即可。如果将来扩展该示例,则可以在Wrapper中嵌入其他组件,而无需更改托管项目。Wrapper组件有两个Prompter实例,以显示它可以在多个实例中正常工作。

<h3>Wrapper</h3>
<h4>Environment:</h4>
<ShowHost></ShowHost>
<h4>First prompt:</h4>
<Prompter></Prompter>
<h4>Second prompt:</h4>
<Prompter></Prompter>

服务你的Blazor

Razor类库本身并没有做很多事情。它需要一个宿主项目。稍微加一点点,我创建的第一个项目是服务器端项目,而不是托管Blazor WebAssembly项目。

事实证明,Blazor具有几种不同的托管模式。尽管WebAssembly仍在预览中,但Blazor Server托管模型已准备好投入生产。您可以在官方文档中了解更多信息。我本人是WebAssembly的粉丝,但是有一些理由使使用服务器端项目有意义。首先,它可以引用Blazor WebAssembly使用的同一Razor类库。其次,它提供了完全集成的调试体验。只需设置您的断点,按F5键,就可以了!

在名为BlazorApp.Server的项目中,我添加了对BlazorApp.Shared的引用。接下来,我需要确保JavaScript文件已正确加载到我的应用程序中。幸运的是,Razor类库公开了一种非常简单的约定来访问嵌入式资源。相对于网页,您可以使用以下约定访问资源:_content/{assemblyname}/{filename}。要包含脚本,只需将以下script标记添加到_Host.cshtml

<script src="_content/BlazorApp.Shared/exampleJsInterop.js"></script>

这是一个手动步骤,必须对其他文件重复执行。Blazor团队有充分的理由不自动包含资源,例如资源的可能性和命名冲突。

接下来,我打开Index.razor并放入Wrapper组件:

@using BlazorApp.Shared
@page "/"
<h1>Hello, world!</h1>
Welcome to your new app.
<Wrapper></Wrapper>

为了调试简便方法,我在Prompter组件中StateHasChanged()的行上放置了一个断点,然后按F5键。我的应用程序使用操作系统版本(请注意是我的服务器或笔记本电脑版本)、日期和按钮进行渲染。

单击输入文本按钮之一将导致显示JavaScript提示,向我展示嵌入共享资源和JavaScript互操作性都在起作用。输入文本并单击确定后,将出现断点,并且我可以检查变量,修改属性,查看调用堆栈并执行我可能想要的几乎任何其他调试任务。现在代码看起来不错,是时候创建Blazor WebAssembly项目了!

调试客户端(Edge版)

创建名为BlazorApp.ClientBlazor WebAssembly项目后,我添加了对服务器端应用程序中使用的同一Razor类库(BlazorApp.Shared)的引用。我使用完全相同的约定来引用JavaScript,仅这次是将script标记放置在wwwroot下方的index.html中,而不是_Host.cshtml中。Index.razor修饰是相同的服务器端的版本。我将启动项目设置为客户端,然后按CTRL + F5启动它。结果看起来几乎相同……除了一个例外。您看到了吗?

万一您错过了它,平台将报告为Unix 1.0.0.0。这是因为该应用程序现在已完全通过WebAssemblyMono的浏览器中运行。其余功能大致相同。

如果您现在需要调试应用程序该怎么办?如果打开调试控制台,您将看到以下消息:

Debugging hotkey: Shift+Alt+D (when application has focus)

很有可能是按下了组合键,结果出现了一个错误,说明了如何修复它。

如果您使用的是Chrome浏览器,那很好。请注意,您需要关闭所有现有的Chrome窗口,并且如果任务栏中有Chrome加速器,也请从中退出。

但是,如果您使用Edge,该怎么办?没问题!关闭所有打开的Edge实例,然后运行以下命令(我只是更改了路径以指向Edge安装,您的安装可能有所不同):

"%programfiles(x86)%\Microsoft\Edge Dev\Application\msedge.exe" --remote-debugging-port=9222 http://localhost:57955

不确定Edge安装的路径是什么?没问题。只需右键单击用于启动它的图标并进入属性。您应该看到带有路径的属性,或者带有目标属性的快捷方式选项卡,其中包含可执行文件的完整路径。

如果您的应用程序在其他端口上运行,请相应地更改URL。这应该再次启动该应用程序。按SHIFT + ALT + D组合键,将打开一个新标签,其中包含一些其他信息。这是我的样子:

您可以在file://下面扩展虚拟文件系统以浏览源代码,并将断点放在服务器端示例中使用的同一StateHasChanged()行上。跳回到主选项卡,单击提示,输入一些文本,然后单击确定。您应该看到已在调试器中暂停消息。转到调试选项卡,您现在可以看到已触发断点。可以在范围下展开右侧面板以检查变量和属性的值。

这就是魔术的结尾!

在此博客文章中,我们探讨了:

  • 使用Razor类库提高代码的可移植性
  • 实施Blazor Server项目以进行高级调试
  • Edge浏览器调试Blazor WebAssembly

您可以从GitHub下拉项目:

 JeremyLikness / AdvancedBlazor

发布了70 篇原创文章 · 获赞 130 · 访问量 42万+

猜你喜欢

转载自blog.csdn.net/mzl87/article/details/103690465