Bob's Blog

Web开发、测试框架、自动化平台、APP开发、机器学习等

返回上页首页

MAUI加Blazor做一个跨平台的记账APP(三)请求后端接口



前面记录了加页面,但是需要从后端请求数据,来灵活地更新页面展示情况,记账毕竟也是要个人特有的,像账户和细目啊这些。于是以登录获取token为例记录一下请求后端接口。

在项目根目录新增Models和Services文件夹。

在Models目录下新增一个文件Token.cs,用以定义后端返回数据中需要处理的字段。

namespace accountingMAUIBlazor.Models;

public class Token
{
	public string username { get; set; }
	public string mail { get; set; }
	public string token { get; set; }
}

在Services目录下先新增一个interface文件IUserService.cs,定义用户的相关行为,这里仅包含获取token。

namespace accountingMAUIBlazor.Services;

public interface IUserService
{
    Task<String> GetTokenAsync();

}

同目录继续新增一个文件UserService.cs,作为对应接口文件的具体实现。这里先将登陆账户写死,等后续修改再调整为传递表单参数。定义是否登录和token值,如果已登录或者token不为空则直接返回,否则就向后端请求token再解析json数据后返回。这里用了异步请求避免卡顿,于是看到async和await,并且需要写作Task。

using System.Text.Json;
using System.Text;
using accountingMAUIBlazor.Models;

namespace accountingMAUIBlazor.Services;

public class UserService : IUserService
{
    public bool IsLoggedIn { get; set; } = false;
    private string _token = string.Empty;

    public async Task<String> GetTokenAsync() //remember to add user parameter
    {
        if (!string.IsNullOrWhiteSpace(_token) || IsLoggedIn)
        {
            Console.WriteLine("no need to request api, return existent token");
            return _token;
        }

        using var httpClient = new HttpClient();
        HttpResponseMessage response;
        try
        {
            var loginData = new {
                username = "Bob",
                password = "Bob"
            };
            var loginContent = new StringContent(JsonSerializer.Serialize(loginData), Encoding.UTF8, "application/json");

            response =
                await httpClient.PostAsync("http://127.0.0.1:8000/external/api/login/", loginContent);
            response.EnsureSuccessStatusCode();
        }
        catch (Exception e)
        {
            Console.WriteLine("Error when request api: " + e.Message);
            return _token;
        }

        var result = await response.Content.ReadAsStringAsync();
        Console.WriteLine("result: " + result);
        try
        {
            _token = JsonSerializer.Deserialize<Token>(result)?.token ?? throw new JsonException();
            IsLoggedIn = true;
        }
        catch (Exception e)
        {
            Console.WriteLine("Error when handle json: " + e.Message);
            return _token;

        }

        return _token;
    }
}

增加完了后需要注意在其他两个地方引用,否则页面调用会报错。

一是_Imports.razor加上

@using accountingMAUIBlazor.Services

二是MauiProgram.cs中加上引用,注意这里用了AddSingleton。这种有三类:

  • AddTransient (Transient objects are always different; a new instance is provided to every controller and every service.)
  • AddScoped (Scoped objects are the same within a request, but different across different requests.)
  • AddSingleton (Singleton objects are the same for every object and every request.)
using Microsoft.Extensions.Logging;
using accountingMAUIBlazor.Data;
using accountingMAUIBlazor.Services;   //here

namespace accountingMAUIBlazor;

public static class MauiProgram
{
	public static MauiApp CreateMauiApp()
	{
		var builder = MauiApp.CreateBuilder();
		builder.UseMauiApp<App>().ConfigureFonts(fonts =>{
			fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
		});

        builder.Services.AddSingleton<IUserService, UserService>();  //here

		builder.Services.AddMauiBlazorWebView();

#if DEBUG
		builder.Services.AddBlazorWebViewDeveloperTools();
		builder.Logging.AddDebug();
#endif

		builder.Services.AddSingleton<WeatherForecastService>();

		return builder.Build();
	}
}

接下来需要再增加一个简单的登陆页面来验证一下,在pages下新增Login.razor和Login.razor.cs。

Login.razor:

@inject NavigationManager NavigationManager
@inject IUserService _userService


<h3>Test Login</h3>
<p>Clicked Times: @click_count</p>
<p>token: @token</p>
<button class="btn btn-primary" @onclick="LoginWithoutInput">Click to login directly</button>

Login.razor.cs:

namespace accountingMAUIBlazor.Pages;

public partial class Login
{
    private string token;
    private int click_count = 0;

    public async void LoginWithoutInput()
    {
        Console.WriteLine("start to login...");
        click_count += 1;
        token = await _userService.GetTokenAsync();
        Console.WriteLine($"Token is: {token}");
        NavigationManager.NavigateTo("/accounts");
    }
}

运行起来后就能看到点击页面上的按钮,则会跳转到accounts页面;可以注释掉NavigateTo这一句,就能看到点击后点击次数会加一显示,token的值要是请求成功也会成功显示出来。当然这里的逻辑不严谨,等后面再改。

下一篇:  MAUI加Blazor做一个跨平台的记账APP(四)表单
上一篇:  MAUI加Blazor做一个跨平台的记账APP(二)新增账户页面

共有0条评论

添加评论

暂无评论