我真的找不到一个可行的例子,也许是因为它根本不可能?
我想要一个 C# 匿名类型对象,如下所示:
var postBody = new
{
friend = new
{
name = "dave",
last ="franz"
},
id = "12345",
login = "mylogin"
};
Run Code Online (Sandbox Code Playgroud)
并通过简单的 http POST 将其发布到我的 Web 服务,帖子正文如下:
{
"friend" :
{
"name" : "dave",
"last" : "franz"
},
"id" : "12345",
"login" : "mylogin"
};
Run Code Online (Sandbox Code Playgroud) 我正在尝试使用MultipartFormDataContent. 为了以块的形式发送文件,我使用它将PushStreamContent数据块从文件流写入输出流,每次写入后刷新:
PushStreamContent pushStreamContent = new PushStreamContent((stream, content, context) => {
byte[] buffer = new byte[4096];
int bytesRead;
do {
bytesRead = fileStream.Read(buffer, 0, 4096);
stream.Write(buffer, 0, bytesRead);
stream.Flush();
}
while(bytesRead != 0);
stream.Close();
});
Run Code Online (Sandbox Code Playgroud)
如果我HttpContent使用以下代码发布此内容,则一切正常:
new HttpClient().PostAsync(destinationUrl, pushStreamContent);
Run Code Online (Sandbox Code Playgroud)
但是,如果将其PushStreamContent添加到 a 中MultipartFormDataContent,如下所示:
MultipartFormDataContent postForm = new MultipartFormDataContent {
{stringContent, "atom"},
{pushStreamContent, "binary"}
};
Run Code Online (Sandbox Code Playgroud)
并将其发布,然后我OutOfMemoryException在 的 lambda 内收到一个PushStreamContent。据推测,它HttpClient正在将整个数据缓冲MultipartFormDataContent到内存中,但由于请求内容非常大,因此失败。我希望客户能够推迟所包含的内容的冲洗PushStreamContent …
根据一些 Microsoft 示例,我得到了这一点:
ASP.NET Core 设置:
app.UseCookieAuthentication(new CookieAuthenticationOptions());
app.UseOpenIdConnectAuthentication(new OpenIdConnectOptions
{
ClientId = Configuration["Authentication:AzureAD:ClientId"],
Authority = Configuration["Authentication:AzureAd:Authority"],
ResponseType = OpenIdConnectResponseType.IdToken,
AutomaticAuthenticate = true,
TokenValidationParameters = new TokenValidationParameters()
});
Run Code Online (Sandbox Code Playgroud)
授权测试端点:
[HttpGet]
[Authorize]
public IActionResult Get()
{
return Ok("SAMPLE TEXT - if you can read this then call it a day :)");
}
Run Code Online (Sandbox Code Playgroud)
客户:
try
{
var result = await authContext.AcquireTokenAsync(WebApiResourceId, WebApiClientId, WebApiRedirectUri, new PlatformParameters(PromptBehavior.Auto));
authorizedClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", result.AccessToken);
var authorizedMessage = await authorizedClient.GetAsync("/AuthorizationTest");
var statusCode = authorizedMessage.StatusCode.ToString();
var message = …Run Code Online (Sandbox Code Playgroud) 我正在使用一个设计不佳的 API,其缺陷之一是,它有一个特定的端点,不应提供特定的自定义标头,而实际上每个其他端点都需要它。因此,它包含在 中DefaultRequestHeaders,因此我不需要将其手动添加到每个请求中。
然而,现在,对于这个特定的端点,我需要删除它,而且我不确定如何或是否可能。让事情变得有些复杂的是,我正在处理一个单例范围的HttpClient实例,所以任何捏造的事情DefaultRequestHeaders都是不可行的。换句话说,我不能做一些像临时删除标头然后在请求之后将其添加回之类的黑客行为,因为这可能会影响正在发出的其他并发请求。令人沮丧的是,即使我下降到使用SendAsync自定义HttpRequestMessage实例,HttpClient 仍然添加标头。
另外,虽然它可以工作,但我真的不想在没有将 HttpClient标头添加到DefaultRequestHeaders. 由于多种原因,在同一个类中使用两个不同的HttpClient实例似乎是一个非常糟糕的主意。
我在这里运气不好,还是在过去一个小时搜索互联网后我错过了一些解决方案?
更新
我确实发现,对于自定义HttpRequestMessage实例,我可以通过将其设置为HttpRequestMessage. 由于它是明确设置的,因此HttpClient不会用默认版本覆盖它。这仍然意味着标头正在发送,但至少它实际上没有值。不过,如果存在的话,仍然对更好的解决方案感兴趣。
我正在尝试访问休息端点https://api.planet.com/auth/v1/experimental/public/users/authenticate。它期望请求正文中有 json。
我可以得到在 Postman 中工作的请求,但不能使用 C#。使用邮递员,我收到预期的无效电子邮件或密码消息,但使用我的代码,无论我尝试如何,我都会收到“错误请求”。
这是发出请求的代码
private void Login()
{
try
{
HttpClient client = new HttpClient();
client.BaseAddress = new Uri("https://api.planet.com/");
client.DefaultRequestHeaders.Accept.Clear();
//ClientDefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("*/*"));
Data.User user = new Data.User
{
email = "myemail@company.com",
password = "sdosadf"
};
var requestMessage = JsonConvert.SerializeObject(user);
var content = new StringContent(requestMessage, Encoding.UTF8, "application/json");
var response = client.PostAsync("auth/v1/experimental/public/users/authenticate", content).Result;
Console.WriteLine(response.ToString());
}
catch (WebException wex )
{
MessageBox.Show(wex.Message) ;
}
}
class User
{
public string email;
public string password;
}
Run Code Online (Sandbox Code Playgroud)
我已经在我的项目中成功使用RateLimiter ( github ) 一段时间了。我最近发现了依赖注入,并尝试按原样迁移我的代码以使用它,但我陷入了 RateLimiter。
文档中的正常用法是
var handler = TimeLimiter
.GetFromMaxCountByInterval(25, TimeSpan.FromMinutes(1))
.AsDelegatingHandler();
var Client = new HttpClient(handler)
Run Code Online (Sandbox Code Playgroud)
但是,如果我尝试在依赖注入期间复制它
public override void Configure(IFunctionsHostBuilder builder)
{
builder.Services.AddHttpClient<IMyApiClient, MyApiClient>(client => client.BaseAddress = new Uri("https://api.myapi.com/"))
.AddPolicyHandler(GetRetryPolicy())
.AddHttpMessageHandler(() => TimeLimiter.GetFromMaxCountByInterval(25, TimeSpan.FromMinutes(1)).AsDelegatingHandler());
}
Run Code Online (Sandbox Code Playgroud)
我收到错误:
[2021-05-17T21:58:00.116Z] Microsoft.Extensions.Http: The 'InnerHandler' property must be null. 'DelegatingHandler' instances provided to 'HttpMessageHandlerBuilder' must not be reused or cached.
[2021-05-17T21:58:00.117Z] Handler: 'ComposableAsync.DispatcherDelegatingHandler'.
[2021-05-17T21:58:00.122Z] An unhandled host error has occurred.
Run Code Online (Sandbox Code Playgroud)
我的类客户端结构(主要是为了单元测试)如下所示:
using System.Net.Http;
using System.Threading.Tasks;
public class MyApiClient : HumbleHttpClient, …Run Code Online (Sandbox Code Playgroud) 我需要进行一系列 HTTP 调用以从第 3 方保管库获取数据库凭据,因为我需要运行此代码Program.cs,或者最晚Startup.cs在添加 DBContext 之前,我需要能够在不使用 DBContext 的情况下进行这些调用使用IHttpClientFactory,因为这需要依赖注入已经初始化。
以下代码在运行时调用时工作正常,但在步骤期间不起作用ConfigureAppConfiguration。
HttpClient client = _clientFactory.CreateClient();
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, $"{_configuration["CredentialsVault:vaultUrl"]}Auth/SignAppIn");
request.Headers.Add("Authorization", $"PS-Auth key={_apiKey}; runas={_runAsUser};");
var response = await client.SendAsync(request);
Run Code Online (Sandbox Code Playgroud)
有没有一种方法可以在不依赖依赖注入的情况下进行 HTTP 调用,或者延迟AddDbContext到依赖注入设置之后?
我尝试创建一个 HttpClient 实例,如下所示:
HttpClient client = new HttpClient();
Run Code Online (Sandbox Code Playgroud)
然而,这似乎不起作用,根据这个问题,它不应该像这样实例化。
我正在开发一个访问速率受限的 API 的集成解决方案。我正在不同端点上(尽管在同一服务器上)使用多个 HTTP 动词对 API 执行各种 CRUD 操作。我多次被指向 Polly,但我还没有想出一个真正有效的解决方案。
这就是我在初创公司中所拥有的:
builder.Services
.AddHttpClient("APIClient", client =>
{
client.BaseAddress = new Uri(C.Configuration.GetValue<string>("APIBaseAddress"));
})
.AddTransientHttpErrorPolicy(builder =>
builder.WaitAndRetryAsync(new []
{
TimeSpan.FromSeconds(1),
TimeSpan.FromSeconds(5),
TimeSpan.FromSeconds(15),
}));
Run Code Online (Sandbox Code Playgroud)
这只是在失败时重试的弹性。我在单例 ApiWrapper 类中有一个 RateLimit 策略:
public sealed class ApiWrapper
{
private static readonly Lazy<ApiWrapper> lazy = new Lazy<ApiWrapper>(() => new ApiWrapper());
public static ApiWrapper Instance { get { return lazy.Value; } }
private IHttpClientFactory _httpClientFactory;
public readonly AsyncRateLimitPolicy RateLimit = Policy.RateLimitAsync(150, TimeSpan.FromSeconds(10), 50); // 150 actions within 10 sec, 50 …Run Code Online (Sandbox Code Playgroud) AnHttpRequestMessage只能发送一次。尝试重新发送会导致InvalidOperationException.
那么 Polly 如何能够规避这种行为,换句话说,使用AddPolicyHandler重试策略时幕后发生了什么?我知道它使用 aDelegatingHandler但它如何能够多次处理同一条消息?
我正在使用HttpClient调用ASP .Net Web API并成功调用操作.此外,我也可以将自定义对象发布到操作中.
现在我面临的问题是,无法发布标量数据类型,如Integer,String等...
下面是我的控制器和调用操作的应用程序代码
//测试调用的应用程序
[Test]
public void RemoveCategory()
{
HttpClient client = new HttpClient();
HttpRequestMessage request = new HttpRequestMessage();
HttpResponseMessage response = client.PostAsJsonAsync<string>("http://localhost:49931/api/Supplier/RemoveCategory/", "9").Result;
Console.WriteLine(response.Content.ReadAsStringAsync().Result);
}
Run Code Online (Sandbox Code Playgroud)
// Web API中的控制器和操作
public class SupplierController : ApiController
{
NorthwindEntities context = new NorthwindEntities();
[HttpPost]
public HttpResponseMessage RemoveCategory(string CategoryID)
{
try
{
int CatId= Convert.ToInt32(CategoryID);
var category = context.Categories.Where(c => c.CategoryID == CatId).FirstOrDefault();
if (category != null)
{
context.Categories.DeleteObject(category);
context.SaveChanges();
return Request.CreateResponse(HttpStatusCode.OK, "Delete successfully CategoryID = " + CategoryID);
}
else …Run Code Online (Sandbox Code Playgroud) c# ×9
.net-core ×2
asp.net-core ×2
polly ×2
.net ×1
azure ×1
cookies ×1
http-post ×1
json ×1
post ×1
resiliency ×1
rest ×1
retry-logic ×1
using ×1
webclient ×1