【发布时间】:2021-01-03 14:37:10
【问题描述】:
好的,我有一个调用服务器端 Web api 端点的 wasm 应用程序。 问题是我从端点的 /wwwroot 目录中获取 index.html 页面作为答案。但是当我用 Postman 处理端点时,我得到了预期的 json 答案。 好的,我将展示我如何使用我的代码执行此操作。
客户端数据流
Search.razor 页面
在这里,当在表单字段中输入搜索文本时,我会调用 Web API 端点。这按预期工作。
... Snip
// UPDATED INFO
<div class="form-group">
<label for="objectType">Select object type</label>
<select id="objectType" class="form-control" @bind="@_searchByNameObjectTypeUuid">
@if (_objectTypes != null)
{
@foreach (var objectType in _objectTypes)
{
@if (objectType.TypeName == "Music")
{
@* This selection value is not set. But why?
<option value="@objectType.Uuid.ToString("D")" selected="selected">@objectType.TypeName</option>
}
else
{
<option value="@objectType.Uuid.ToString("D")">@objectType.TypeName</option>
}
}
}
</select>
</div>
// UPDATED INFO END
<div class="form-group">
<label for="objectName">Object name:<br/></label>
<input type="text" class="form-control" id="objectName" @onkeydown="@SearchByNameOnEnter" @bind-value="@_searchByNameObjectNamePhrase" @bind-value:event="oninput"/>
</div>
...Snip
@code {
private string _searchByNameObjectNamePhrase = string.Empty;
private async Task SearchByNameOnEnter(KeyboardEventArgs e)
{
if ((e.Code == "Enter" || e.Code == "NumpadEnter") && !string.IsNullOrWhiteSpace(_searchByNameObjectNamePhrase))
{
_searchResult = await ServerApiClient.SearchObjectsByNamePhrase(_searchByNameObjectTypeUuid, _searchByNameObjectNamePhrase);
}
}
}
ServerApiClientService.cs Web API 客户端服务
通过这个我调用不同的 Web API 端点,从后端的数据库中获取数据。
GetDdsObjectAttributeValueCount() 方法按预期工作。
SearchObjectsByNamePhrase(string objTypeUuid, string searchTermPhrase) 方法将文件 /wwwroot/index.html 作为答案发送给我。 (详情请在代码中显示cmets)
namespace WebAssembly.Client.Services
{
public class ServerApiClientService : IServerApiClientService
{
#region Constants - Static fields - Fields
private readonly HttpClient _httpClient;
#endregion
#region Constructors and Destructors
public ServerApiClientService(HttpClient httpClient)
{
_httpClient = httpClient;
}
#endregion
#region Methods
// This endpoint request work as expected
public async Task<IEnumerable<ObjectAttributeValueCount>> GetDdsObjectAttributeValueCount()
{
IEnumerable<ObjectAttributeValueCount> result =
await _httpClient
.GetFromJsonAsync<List<ObjectAttributeValueCount>>("/api/DdsDashboard/GetDdsObjectAttributeValueCount");
return (result ?? Array.Empty<ObjectAttributeValueCount>()).AsQueryable();
}
// This endpoint request NOT work as expected
public async Task<IEnumerable<SearchResultItem>> SearchObjectsByNamePhrase(string objTypeUuid, string searchTermPhrase)
{
// For test i have called as string and i get HTML response. wwwroot/index.html is comming back.
var asJsonString =
await _httpClient
.GetStringAsync($"/api/DdsDashboard/SearchObjectsByNamePhrase/{objTypeUuid}/{searchTermPhrase}");
// And here i get the exception "System.Text.Json.JsonReaderException"
// '<' is an invalid start of a value
IEnumerable<SearchResultItem> result =
await _httpClient
.GetFromJsonAsync<List<SearchResultItem>>($"/api/DdsDashboard/SearchObjectsByNamePhrase/{objTypeUuid}/{searchTermPhrase}");
return (result ?? Array.Empty<SearchResultItem>()).AsQueryable();
}
#endregion
}
}
服务器端数据流
DdsDashboardController.cs 作为 Web API 控制器
当我使用 Postman 处理此控制器中的所有方法(路由)时,它们都可以正常工作。
路由 [HttpGet("GetDdsObjectAttributeValueCount")] 和路由 [HttpGet("GetDdsObjectTypeStatistic")] 也适用于 ServerApiClientService.cs。
只有路线 [HttpGet ("SearchObjectsByNamePhrase / {objTypeId} / {searchTerm}")] 只适用于 Postman。
namespace WebAssembly.Server.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class DdsDashboardController : ControllerBase
{
#region Constants - Static fields - Fields
private readonly IDdsRepository _repository;
#endregion
#region Constructors and Destructors
public DdsDashboardController(IDdsRepository repo)
{
_repository = repo;
}
#endregion
#region Methods
[HttpGet("GetDdsObjectAttributeValueCount")]
public async Task<IEnumerable<ObjectAttributeValueCount>> GetDdsObjectAttributeValueCount()
{
return await _repository.GetDdsObjectAttributeValueCount();
}
[HttpGet("GetDdsObjectTypeStatistic")]
public async Task<IEnumerable<ObjectTypeStatistic>> GetDdsObjectTypeStatistic()
{
return await _repository.GetDdsObjectTypeStatistic();
}
// This method is called and worked as expected. When i call this endpoint with Postman all is fine. Correct JSON response.
[HttpGet("SearchObjectsByNamePhrase/{objTypeId}/{searchTerm}")]
public async Task<IEnumerable<SearchResultItem>> SearchObjectsByNamePhrase(string objTypeId, string searchTerm)
{
// Correct result from my database. I have checked with an breakpoint.
var result = await _repository.SearchObjectsByNamePhrase(objTypeId, searchTerm);
return result;
}
#endregion
}
}
Startup.cs
配置方法
public void Configure(IApplicationBuilder app)
{
if (Env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseWebAssemblyDebugging();
}
else
{
app.UseExceptionHandler("/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
app.UseHttpsRedirection();
}
app.UseBlazorFrameworkFiles();
app.UseStaticFiles();
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapRazorPages();
endpoints.MapControllers();
endpoints.MapFallbackToFile("index.html");
});
}
ConfigureServices 方法
public void ConfigureServices(IServiceCollection services)
{
SqlMapper.AddTypeHandler(new MySqlGuidTypeHandler());
SqlMapper.RemoveTypeMap(typeof(Guid));
SqlMapper.RemoveTypeMap(typeof(Guid?));
services.AddControllersWithViews();
services.AddRazorPages();
services.AddScoped<IDdsRepository, DdsRepository>();
var dbConnectionSettings = new DdsDbConnectionConfiguration(Configuration.GetSection("DdsDbSettings"));
services.AddSingleton(dbConnectionSettings);
if (!Env.IsDevelopment())
{
services.AddHttpsRedirection(options =>
{
options.RedirectStatusCode = StatusCodes.Status308PermanentRedirect;
options.HttpsPort = 443;
});
}
}
向邮递员提出要求
我希望我已经提供了足够的信息来说明为什么这不起作用。
更新
好的。问题是表单控件的绑定仅在我手动进行选择更改时才起作用。在渲染不工作时设置一个选择。
<div class="form-group">
<label for="objectType">Select object type</label>
<select id="objectType" class="form-control" @bind="@_searchByNameObjectTypeUuid">
@if (_objectTypes != null)
{
@foreach (var objectType in _objectTypes)
{
@if (objectType.TypeName == "Music")
{
<option value="@objectType.Uuid.ToString("D")" selected="selected">@objectType.TypeName</option>
}
else
{
<option value="@objectType.Uuid.ToString("D")">@objectType.TypeName</option>
}
}
}
</select>
</div>
这就是为什么没有设置_searchByNameObjectTypeUuid 值的原因。
还有endpoints.MapFallbackToFile(" index.html ")。
我在OnInitializedAsync() 方法中设置了_searchByNameObjectTypeUuid 的值,我还加载了_objectTypes。
protected override async Task OnInitializedAsync()
{
_objectTypes = await DdsApiClient.GetObjectTypes();
_searchByNameObjectTypeUuid = _objectTypes.SingleOrDefault(x => x.TypeName == "Music")?.Uuid.ToString("D");
}
如果有人知道如何在渲染时使用 foreach 循环设置值,我将不胜感激。
感谢@Neil W 的帮助。
【问题讨论】:
-
尝试首先将您的 clientAPI 中的结果放入 HttpResponseMessage 中。然后检查那个。你要返回什么状态码? >>>> HttpResponseMessage res = await _httpClient .GetAsync($"/api/DdsDashboard/SearchObjectsByNamePhrase/{objTypeUuid}/{searchTermPhrase}"); >>> 这可能会给你一个线索。
-
感谢 Neil W。这确实给了一个提示。
{objTypeUuid}未设置为初始值。我会更新我的问题。
标签: c# asp.net-core blazor-webassembly