Estou tentando fazer um decimal ter apenas dois pontos. Por exemplo: eu tentaria fazer 1,2345 = 1,23.
Tentei 'String.Format("{0.0.00}", cats.ToString());' mas ocorreu um erro, basicamente dizendo que não estava no formato correto.
Estou tentando fazer um decimal ter apenas dois pontos. Por exemplo: eu tentaria fazer 1,2345 = 1,23.
Tentei 'String.Format("{0.0.00}", cats.ToString());' mas ocorreu um erro, basicamente dizendo que não estava no formato correto.
private Texture2D defaultCursor; // Store the original cursor
void Start()
{
Cursor.SetCursor(defaultCursor, Vector2.zero, CursorMode.Auto); // Store the default cursor
}
fazendo assim a variável defaultCursor será nula e portanto não poderei usá-la mais tarde no código.
Quero que quando eu usar em algum lugar do meu código o Cursor.SetCursor com minha imagem de textura personalizada, eu consiga alterá-la de volta para a textura padrão do cursor do mouse quando necessário.
Vi que existe um MouseCursor e você pode usar, por exemplo, MouseCursor.Pan ou MouseCursor.Arrow, mas como posso alterar o formato do cursor do mouse para este Pan ou Arrow? sem textura personalizada.
Atualmente, estou aprendendo sobre gerenciamento de erros em projetos de API Web do ASP.NET Core para tentar encontrar uma solução elegante que garanta que um ProblemDetails
seja sempre retornado quando algo der errado.
Estou usando o WeatherForecast
modelo de API padrão que é criado ao criar um novo projeto de API Web em C#/ASP.NET Core 8 com controladores.
Implementei um manipulador de exceções personalizado; no entanto, estou descobrindo que ele nem sempre funciona.
Quando chamo a API usando Postman
para causar o erro, estou obtendo o ProblemDetails
código de status e as informações de cabeçalho corretos; no entanto, quando chamo a API a partir do recurso "tente" na Swagger
interface, estou obtendo o código de status errado (um erro interno 500) com detalhes de exceção em vez de um ProblemDetails
e as informações de cabeçalho erradas.
Analisando isso, descobri que na minha GlobalExceptionHandler
classe (que implementa IExceptionHandle
a interface), o ProblemDetailsService.TryWriteAsync(...)
método retorna false
se eu estiver tentando o código do Swagger; no entanto, quando executo exatamente o mesmo código chamando-o do Postman, o ProblemDetailsService.TryWriteAsync(...)
método retorna true
.
Coloquei um caso para quando o 'ProblemDetailsService.TryWriteAsync(...)' retornar falha para que eu pudesse tentar escrever diretamente ProblemDetailsContext
no httpContext.Response
.
Quando fiz isso, consegui capturar a seguinte exceção (novamente, isso só ocorre ao usar o recurso Try Code do Swagger... não ao chamar do Postman):
A serialização e desserialização de instâncias 'System.Type' não são suportadas. Caminho: $.HttpContext.Features.Key."
Não sei por que isso está falhando.
Estou procurando ajuda sobre como garantir que meu gerenciamento de erros se comporte da mesma maneira, independentemente de como a API é chamada.
Esta é a implementação para minha GlobalExceptionHandler
classe:
public class GlobalExceptionHandler : IExceptionHandler
{
private readonly IProblemDetailsService _problemDetailsService;
public GlobalExceptionHandler(IProblemDetailsService problemDetailsService)
{
if (problemDetailsService == null) throw new ArgumentException(nameof(problemDetailsService));
_problemDetailsService = problemDetailsService;
}
public async ValueTask<bool> TryHandleAsync(HttpContext httpContext, Exception exception, CancellationToken cancellationToken)
{
var message = exception switch
{
ArgumentException => ((ArgumentException)exception).Message,
ValidationException => ((ValidationException)exception).Message,
_ => $"Internal Server Error ({exception.GetType().Name})"
};
int status = exception switch
{
ArgumentException => (int)HttpStatusCode.BadRequest,
ValidationException => (int)HttpStatusCode.BadRequest,
_ => (int)HttpStatusCode.InternalServerError
};
ProblemDetails problemDetails = new()
{
Title = $"Bad Request: {exception.GetType().Name}", // human-readable summary of the problem type
Detail = message, //detailed explanation specific to the problem
Status = status,
Instance = httpContext.Request.GetEncodedUrl(),
Type = exception.HelpLink
};
var errorcontext = new ProblemDetailsContext()
{
HttpContext = httpContext,
ProblemDetails = problemDetails,
//Exception = exception,
AdditionalMetadata = null
};
httpContext.Response.Clear();
httpContext.Response.StatusCode = status;
var written = await _problemDetailsService.TryWriteAsync(errorcontext);
if (!written)
{
try
{
await httpContext.Response.WriteAsJsonAsync<ProblemDetailsContext>(errorcontext);
written = true;
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
written = false;
}
}
return written;
}
}
Este é meu Program.cs
:
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using System.Net;
using System;
using System.ComponentModel.DataAnnotations;
using Microsoft.AspNetCore.Http.Extensions;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using System.Net.Http;
using Microsoft.AspNetCore.Diagnostics;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddControllers();
// Add services to the container.
builder.Services.AddExceptionHandler<ProblemDetailsScratchPad.GlobalExceptionHandler>(); // Using a custom exception handler that converts the exception into a Problem Details
builder.Services.AddProblemDetails(); // required for using the exception handler with the custom problem details exception handler code because it adds the services required for Problem Details
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.UseExceptionHandler(opt => { }); //adding the custom GlobalExceptionHandler to the app's pipeline
app.UseAuthorization();
app.MapControllers();
app.Run();
E esta é a implementação para meu WeatherForecastController
(não que chamar o post ou get irá lançar a exceção a ser tratada pelo manipulador de exceção personalizado)
[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
private readonly ILogger<WeatherForecastController> _logger;
public WeatherForecastController(ILogger<WeatherForecastController> logger)
{
_logger = logger;
}
[HttpGet("GetWeatherForecast")]
public ActionResult<IEnumerable<object>> GetWeatherForecast()
{
throw new ArgumentException("Please provide a valid value for a week day: between 0 and 6");
}
[HttpPost("PostWeatherForecastDTO")]
public ActionResult<IEnumerable<object>> PostWeatherForecastDTO()
{
throw new Exception("Please provide a valid value for a week day: between 0 and 6");
}
}
Eu tenho a imagem construída assim usando a execução
compilação docker --tag=api --file=Dockerfile_01 --no-cache --progress=plain .
com base no Dockerfile_01 abaixo.
DE mcr.microsoft.com/dotnet/sdk:8.0 COMO build
WORKDIR /bin
COPIAR *.csproj ./
EXECUTAR dotnet restore
COPIAR . ./
EXECUTAR dotnet publish --configuration Release --output /release
DE mcr.microsoft.com/dotnet/aspnet:8.0
WORKDIR /bin
COPIAR --from=build /release .
EXPOSE 8080 8081
CMD ["dotnet", "Api.dll"]
Eu inicio a execução do meu contêiner
docker run --detach --publish 5001:8080 --publish 7001:8081 --name WebApi api
e parece funcionar, o log me diz que o programa escuta na porta 8080 etc. No entanto, quando navego para http://localhost:5001, recebo 404. Quando disparo diretamente do VS usando o perfil correspondente, consigo ver o Swagger, como esperado.
Como posso solucionar o problema?
A única coisa inesperada que vejo está no log, me dizendo que o redirecionamento para o protocolo seguro falhou devido a alguma confusão nas portas. Esse é um problema de amanhã, no entanto, e tento ir para 5001, que é HTTP, por enquanto.
2025-02-14 17:56:41 info: Microsoft.Hosting.Lifetime[14]
2025-02-14 17:56:41 Agora ouvindo em: http://[::]:8080
2025-02-14 17:56:41 info: Microsoft.Hosting.Lifetime[0]
2025-02-14 17:56:41 Aplicativo iniciado. Pressione Ctrl+C para desligar.
2025-02-14 17:56:41 info: Microsoft.Hosting.Lifetime[0]
2025-02-14 17:56:41 Ambiente de hospedagem: Produção
2025-02-14 17:56:41 info: Microsoft.Hosting.Lifetime[0]
2025-02-14 17:56:41 Caminho raiz do conteúdo: /usr/bin
2025-02-14 17:57:02 warn: Microsoft.AspNetCore.HttpsPolicy.HttpsRedirectionMiddleware[3]
2025-02-14 17:57:02 Falha ao determinar a porta https para redirecionamento.
Suspeito que há algo suspeito com a forma como configurei as portas, mas não consigo ver onde. Ele segue a sugestão desta resposta também. Testei várias combinações diferentes, mas não notei nada útil.
Naturalmente, testei / , /swagger e /swagger.html só para ter certeza, embora eu saiba que não é esse o problema.
Tenho a seguinte classe para obter uma resposta de API:
[JsonObject]
[Serializable]
public class Root
{
public Metadata metadata { get; set; }
public List<Result> result { get; set; }
}
[JsonObject]
[Serializable]
public class GroupRecord
{
public string groupNumber { get; set; }
}
[JsonObject]
[Serializable]
public class Metadata
{
public int totalCount { get; set; }
public int page { get; set; }
public int pageCount { get; set; }
}
[JsonObject]
[Serializable]
public class Npi
{
public DateTime EffectiveDate { get; set; }
}
[JsonObject]
[Serializable]
public class Result
{
public string Name { get; set; }
public Npi npi { get; set; }
public List<GroupRecord> aGroupRecord { get; set; }
}
Estou tentando obter o resultado que corresponde a um dado groupNumber
e tem o mais recente EffectiveDate
com LINQ.
Aqui está o código do meu aplicativo que pensei que deveria funcionar:
string groupNumber = "SALT"
Root dataObject = response.Content.ReadAsAsync<Root>().Result;
if (dataObject.result.Count >= 1)
{
var result = dataObject.result.Where(x => x.aGroupRecord.Where(a => a.groupNumber == groupNumber).OrderByDescending(x.npi => x.npi.EffectiveDate)).FirstOrDefault();
}
Depois de mudar do Azure TelemetryClient para o OpenTelemetry, estamos vendo uma tonelada de CustomMetrics no Application Insights, tantas que preenchemos nossa cotação em menos de uma hora.
Olhando dentro do Application Insights > Logs, posso ver isto: https://imgur.com/a/afu4aCM que mostra pelo menos 25 entradas todas no mesmo milissegundo. Então eu gostaria de começar filtrando esses logs, mas sendo novo no OpenTelemetry, estou tendo dificuldades com a documentação.
O aplicativo em execução é um site asp.net core e nossa configuração OpenTelemetry é bem básica:
public static void RegisterOpenTelemetry(this IServiceCollection service, IConfiguration configuration)
{
service.AddOpenTelemetry()
.UseAzureMonitor(options =>
{
options.ConnectionString = configuration["ApplicationInsights:ConnectionString"];
options.EnableLiveMetrics = true;
})
.WithTracing(x =>
{
x.AddSqlClientInstrumentation(options =>
{
options.SetDbStatementForText = true;
options.RecordException = true;
});
})
.WithMetrics(x =>
{
x.AddSqlClientInstrumentation();
});
service.Configure<AspNetCoreTraceInstrumentationOptions>(options =>
{
options.RecordException = true;
});
}
tl;dr: Se eu quiser filtrar todas as 'http.client_open_connections', como posso fazer isso?
desde já, obrigado
Como um exemplo simplificado do meu problema, tenho um array de ISomeType
, e quero fazer um loop sobre todos os elementos naquele array que são realmente MyType
, mas estou recebendo avisos IDE0220 "Add explicit cast in foreach loop" que não acho que se apliquem. Aqui está um exemplo de código:
public interface ISomeType {
void DoThing();
}
public class MyType: ISomeType {
void DoThing() { /* do something */ }
void DoMyTypeThing() { /* do something specific to MyType */ }
}
public class YourType: ISomeType {
void DoThing() { /* do something */ }
void DoMyTypeThing() { /* do something specific to MyType */ }
}
ISomeType[] maybeMyTypes = [new MyType()];
// I get the error on this line because I cast the element into `MyType`
foreach (MyType foobar in maybeMyTypes.Where(i => i.GetType() == typeof(MyType))) {
// use the MyType methods availbale on foobar
}
O compilador reclama que ele converte implicitamente os elementos de maybeFooBars
em MyType
, e que isso pode falhar em tempo de execução, então devo ser explícito sobre a conversão:
// Code with violations. var list = new List<object>(); foreach (string item in list) { } // Fixed code. var list = new List<object>(); foreach (string item in list.Cast<string>())
Meu código poderia realmente falhar em tempo de execução, já que estou verificando o tipo e apenas fazendo cast implicitamente se o tipo estiver correto? Ou o compilador C# não é inteligente o suficiente para ver que eu me protegi contra os tipos estarem incorretos?
Estou tentando enviar uma mensagem da API de nuvem do WhatsApp usando tipos anônimos em c#. O código a seguir funciona bem:
// Request Body
var body = new
{
messaging_product = "whatsapp",
to = "92" + patient.Phone.TrimStart('0'), // Use the entered recipient's phone number
type = "template",
template = new
{
name = "appointment_new",
language = new
{
code = "en"
},
components = new[]
{
new
{
type = "header",
parameters = new[]
{
new
{
type = "text",
text = clinicname??"Appointment"
}
}
},
new
{
type = "body",
parameters = new[]
{
new
{
type = "text",
text = $"test"
}
}
}
}
},
message = "test" // Use the entered message
};
Mas eu quero enviar um arquivo PDF no header usando o mediaId. Então eu faço essa alteração por exemplo:
// Request Body
var body = new
{
messaging_product = "whatsapp",
to = "92" + patient.Phone.TrimStart('0'), // Use the entered recipient's phone number
type = "template",
template = new
{
name = "appointment_new",
language = new
{
code = "en"
},
components = new[]
{
new
{
type = "header",
parameters = new[]
{
new
{
type = "document", //////change
document = new //////change
{
id = mediaId //////change
}
}
}
},
new
{
type = "body",
parameters = new[]
{
new
{
type = "text",
text = $"test"
}
}
}
}
},
message = "test" // Use the entered message
};
Mas o Visual Studio dá erro de sintaxe aqui: No best type found for implicitly-typed array
Quero entender o porquê? Qual é a diferença entre o primeiro código e o segundo? A AI também lança a segunda versão e não tem outras ideias.
Li que a documentação diz que definir o status como Cancelado requer três condições:
OperationCanceledException
(ou seu tipo de exceção derivado, como TaskCanceledException
) é lançadotoken.IsCancellationRequested
é verdadetoken
no delegado passado para OperationCanceledException
é idêntico ao token
passado como parâmetro na criação da tarefaNo entanto, o exemplo a seguir lança diretamente sem nenhum token, mas obtém sucesso no cancelamento. É porque o token é uma estrutura, então o valor padrão sempre satisfaz as duas últimas condições? Não estou confiante sobre esse pensamento, espero obter alguma explicação se eu estiver errado
var task = Task.Run(() =>
{
throw new OperationCanceledException();
});
try
{
task.Wait();
}
catch (AggregateException)
{
Console.WriteLine(task.Status); // Cancelled
}
O seguinte cenário de exemplo:
Tenho a coluna A
com
RowIndex: 4
ColumnIndex: 7
Quero deslocar a coluna A
11 lugares para a esquerda para que meus índices de coluna resultantes ( B
) sejam
RowIndex: 2
ColumnIndex: 6
Para piorar a situação, a tabela é uma subtabela e, portanto, não começa no índice 0, 0, mas algo como 4, 2, como neste exemplo é possível
Tenho quase certeza de que isso pode ser resolvido por meio de cálculo de módulo, mas meu cérebro se recusa a me dar a fórmula correta.
Comecei em c# até agora com essa codificação, mas isso não parece estar certo, obviamente ( https://dotnetfiddle.net/5iEqgD ):
public static void Main()
{
int minColumnIndex = 4;
int maxColumnIndex = 8;
int minRowIndex = 2;
int maxRowIndex = 5;
int cellARowIndex = 4;
int cellAColumnIndex = 7;
int shiftCellToTheLeft = 11;
int cellBColumnIndex = cellAColumnIndex - ((maxColumnIndex - minColumnIndex + 1) % shiftCellToTheLeft);
int cellBRowIndex = cellARowIndex - ((maxColumnIndex - maxColumnIndex + 1) % shiftCellToTheLeft);
Console.WriteLine("cellBColumnIndex: " + cellBColumnIndex);
Console.WriteLine("cellBRowIndex: " + cellBRowIndex);
// Result:
// cellBColumnIndex: 2
// cellBRowIndex: 3
}
O que estou fazendo errado aqui?