asp.net核心剃须刀页面调用rest服务以及如何等待响应



我有一个剃刀页面,它调用rest服务来查找所提供地址的地理代码。调用在完成查找时使用事件触发的回调。一切都在工作,但时间不合适。当回调完成时,页面已经绘制好了,我需要回调的结果来正确绘制页面。

using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Options;
using Northwind.ModelsDB;
using System.Runtime.Serialization.Json;
using BingMapsRESTToolkit;
using System.Net;
namespace Northwind.Pages.CustomerPages
{
public class DetailsModel : PageModel
{
private readonly Northwind.ModelsDB.NorthwindContext _context;
private readonly IOptions<MyConfig> config;
public string BingMapKey { get; private set; }
public double latitude { get; private set; }
public double longitude { get; private set; }
public string query { get; private set; }
public VIndividualCustomer VIndividualCustomer { get; private set; }
public DetailsModel(Northwind.ModelsDB.NorthwindContext context, IOptions<MyConfig> configg)
{
_context = context;
this.config = configg;
BingMapKey = config.Value.BingMapKey;
}
public async Task<IActionResult> OnGetAsync(int? id)
{
if (id == null)
{
return NotFound();
}
VIndividualCustomer = await _context.VIndividualCustomer
.AsNoTracking()
.FirstOrDefaultAsync(m => m.BusinessEntityId == id);
if (VIndividualCustomer == null)
{
return NotFound();
}
query = VIndividualCustomer.AddressLine1 + " " +
VIndividualCustomer.AddressLine2 + ", " +
VIndividualCustomer.City + ", " +
VIndividualCustomer.StateProvinceName + ", " +
VIndividualCustomer.PostalCode;
query = "1 Microsoft Way, Redmond, WA";
Uri geocodeRequest = new Uri(string.Format("http://dev.virtualearth.net/REST/v1/Locations?q={0}&key={1}", query, BingMapKey));
GetResponse(geocodeRequest, (x) =>
{
var location = (BingMapsRESTToolkit.Location)x.ResourceSets[0].Resources[0];
latitude = location.GeocodePoints[0].Coordinates[0];
longitude = location.GeocodePoints[0].Coordinates[1];
});
return Page();
}
private void GetResponse(Uri uri, Action<Response> callback)
{
System.Net.WebClient wc = new WebClient();
wc.OpenReadCompleted += (o, a) =>
{
if (callback != null)
{
DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(Response));
callback(ser.ReadObject(a.Result) as Response);
}
};
wc.OpenReadAsync(uri);

}

}}

您的方法永远不会更新,因为响应已经发送到客户端。您需要阻止该方法(使用HttpClient(并等待响应:

public async Task<IActionResult> OnGetAsync(int? id)
{
// this "reads" better
if (id.HasValue)
{
return NotFound();
}
VIndividualCustomer = await _context.VIndividualCustomer
.AsNoTracking()
.FirstOrDefaultAsync(m => m.BusinessEntityId == id);
if (VIndividualCustomer == null)
{
return NotFound();
}
query = VIndividualCustomer.AddressLine1 + " " +
VIndividualCustomer.AddressLine2 + ", " +
VIndividualCustomer.City + ", " +
VIndividualCustomer.StateProvinceName + ", " +
VIndividualCustomer.PostalCode;
query = "1 Microsoft Way, Redmond, WA";
// string interpolation
//https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/tokens/interpolated
var url = $"http://dev.virtualearth.net/REST/v1/Locations?q={query}&key={BingMapKey}";
var geocodeRequest = new Uri(url);
var ser = new DataContractJsonSerializer(typeof(Response));
var response = await (new HttpClient()).GetAsync(geocodeRequest);
var json = await response.Content.ReadAsStringAsync();
var x = ser.ReadObject(json) as Response;     
var location = (BingMapsRESTToolkit.Location)x.ResourceSets[0].Resources[0];
latitude = location.GeocodePoints[0].Coordinates[0];
longitude = location.GeocodePoints[0].Coordinates[1];
return Page();
}

与您自己的代码最接近的代码是以下代码片段:

private async Task GetResponseAsync(Uri uri, Action<Response> callback) {
System.Net.Http.HttpClient wc = new HttpClient();
var response = await wc.GetAsync(uri);
if (callback != null) {
var stream = await response.Content.ReadAsStreamAsync();
DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(Response));
callback(ser.ReadObject(stream) as Response);
}
}

并称之为:

await GetResponse(geocodeRequest, (x) =>
{
/ bla bla bla...
});

然而,它不是一个好的重构代码。但能胜任这份工作。

最新更新