Skip to content

Instantly share code, notes, and snippets.

@danielplawgo
Created May 5, 2021 06:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save danielplawgo/8ba409bf37a04b83d559615bcc92efd4 to your computer and use it in GitHub Desktop.
Save danielplawgo/8ba409bf37a04b83d559615bcc92efd4 to your computer and use it in GitHub Desktop.
Blazor - walidacja - Web API
public class BasePage : ComponentBase
{
protected FormValidator FormValidator;
protected void ShowError(Result result, object model = null)
{
FormValidator?.ShowError(result, model);
}
protected void ShowMessage(string message)
{
FormValidator?.ShowMessage(message);
}
}
[ApiController]
public class CreateProduct : Controller
{
private readonly IValidator<CreateProductCommand> _validator;
public CreateProduct(IValidator<CreateProductCommand> validator)
{
_validator = validator;
}
[Route("api/products")]
public async Task<ActionResult> Create(CreateProductCommand command)
{
var validationResult = await _validator.ValidateAsync(command);
if (validationResult.IsValid == false)
{
return BadRequest(validationResult.ToResult());
}
return Ok(Result.Ok(Guid.NewGuid()));
}
public class CreateProductCommandValidator : AbstractValidator<CreateProductCommand>
{
public CreateProductCommandValidator()
{
RuleFor(c => c.Name)
.NotEmpty();
}
}
}
@inherits BasePage
@page "/products/create"
<h3>CreateProduct</h3>
<EditForm Model="Model" OnSubmit="OnSubmit">
<FormValidator @ref="FormValidator" />
<div class="row">
<div class="col-12">
<div class="form-group row">
<label for="name" class="col-sm-3">Nazwa:</label>
<InputText id="name" class="form-control col-sm-8" @bind-Value="@Model.Name"></InputText>
<ValidationMessage class="offset-sm-3 col-sm-8" For="@(() => Model.Name)" />
</div>
</div>
</div>
<div class="row">
<div class="col-12">
<button class="btn btn-primary">Zapisz</button>
</div>
</div>
</EditForm>
public partial class CreateProduct
{
public CreateProductCommand Model = new CreateProductCommand();
[Inject]
public IHttpService HttpService { get; set; }
private async Task OnSubmit()
{
var result = await HttpService.Post<Result<Guid>>("api/products", Model, CancellationToken.None);
if (result.Success)
{
ShowMessage("Dodano produkt");
}
else
{
ShowError(result, Model);
}
}
}
public class CreateProductCommand
{
public string Name { get; set; }
}
@if (string.IsNullOrEmpty(Message) == false)
{
if (Type == MessageType.Success)
{
<div class="alert alert-success" role="alert">
@Message
</div>
}
else if (Type == MessageType.Error)
{
<div class="alert alert-danger" role="alert">
@Message
</div>
}
}
public partial class FormValidator
{
[CascadingParameter]
public EditContext CurrentEditContext { get; set; }
protected ValidationMessageStore ValidationMessageStore { get; set; }
public string Message { get; set; }
public MessageType Type { get; set; }
protected override void OnInitialized()
{
base.OnInitialized();
if (this.CurrentEditContext == null)
{
throw new InvalidOperationException();
}
ValidationMessageStore = new ValidationMessageStore(CurrentEditContext);
}
public void ShowError(Result result, object model)
{
ClearMessages(false);
if (result.Success == false)
{
ShowMessage("Błąd w formularzu", MessageType.Error);
ValidationMessageStore.Clear();
foreach (var error in result.Errors.Where(e => string.IsNullOrEmpty(e.PropertyName) == false))
{
var fieldIdentifier = new FieldIdentifier(model, error.PropertyName);
ValidationMessageStore.Add(fieldIdentifier, error.Message);
}
}
CurrentEditContext.NotifyValidationStateChanged();
}
public void ShowMessage(string message)
{
ShowMessage(message, MessageType.Success);
}
public void ShowMessage(string message, MessageType type)
{
if (type == MessageType.Success)
{
ClearMessages(true);
}
Message = message;
Type = type;
StateHasChanged();
}
public void ClearMessages(bool clearValidationMessages)
{
if (clearValidationMessages)
{
ValidationMessageStore.Clear();
CurrentEditContext.NotifyValidationStateChanged();
}
Message = string.Empty;
StateHasChanged();
}
public enum MessageType
{
Success,
Error
}
}
public class HttpService : IHttpService
{
private readonly string _baseAddress;
public HttpService(IWebAssemblyHostEnvironment hostEnvironment)
{
_baseAddress = hostEnvironment.BaseAddress;
}
public async Task<Result<T>> Get<T>(string path, CancellationToken cancellationToken)
{
try
{
return await CreateRequest(path)
.GetJsonAsync<Result<T>>(cancellationToken);
}
catch (FlurlHttpException ex)
{
return await HandleException<T>(ex);
}
catch (Exception ex)
{
return await HandleException<T>(ex);
}
}
public async Task<Result<T>> Post<T>(string path, object data, CancellationToken cancellationToken)
{
try
{
return await CreateRequest(path)
.PostJsonAsync(data, cancellationToken)
.ReceiveJson<Result<T>>();
}
catch (FlurlHttpException ex)
{
return await HandleException<T>(ex);
}
catch (Exception ex)
{
return await HandleException<T>(ex);
}
}
public async Task<Result<T>> Put<T>(string path, object data, CancellationToken cancellationToken)
{
try
{
return await CreateRequest(path)
.PutJsonAsync(data, cancellationToken)
.ReceiveJson<Result<T>>();
}
catch (FlurlHttpException ex)
{
return await HandleException<T>(ex);
}
catch (Exception ex)
{
return await HandleException<T>(ex);
}
}
public async Task<Result> Delete<T>(string path, CancellationToken cancellationToken)
{
try
{
return await CreateRequest(path)
.DeleteAsync(cancellationToken)
.ReceiveJson<Result>();
}
catch (FlurlHttpException ex)
{
return await HandleException<T>(ex);
}
catch (Exception ex)
{
return await HandleException<T>(ex);
}
}
private IFlurlRequest CreateRequest(string path)
{
var url = _baseAddress
.AppendPathSegment(path);
return new FlurlRequest(url);
}
private static async Task<Result<T>> HandleException<T>(FlurlHttpException ex)
{
var result = await ex.GetResponseJsonAsync<Result>();
if (result != null && result.Success == false)
{
return Result.Failure<T>(result.Errors);
}
return await HandleException<T>(ex as Exception);
}
public static Task<Result<T>> HandleException<T>(Exception ex)
{
return Task.FromResult(Result.Failure<T>("Przepraszamy nastąpił błąd..."));
}
}
public interface IHttpService
{
Task<Result<T>> Get<T>(string path, CancellationToken cancellationToken);
Task<Result<T>> Post<T>(string path, object data, CancellationToken cancellationToken);
Task<Result<T>> Put<T>(string path, object data, CancellationToken cancellationToken);
Task<Result> Delete<T>(string path, CancellationToken cancellationToken);
}
public class Result
{
public bool Success { get; set; }
public IEnumerable<ErrorMessage> Errors { get; set; }
public static Result<T> Ok<T>(T value)
{
return new Result<T>()
{
Success = true,
Value = value
};
}
public static Result<T> Failure<T>(string message)
{
var result = new Result<T>();
result.Success = false;
result.Errors = new List<ErrorMessage>()
{
new ErrorMessage()
{
Message = message
}
};
return result;
}
public static Result<T> Failure<T>(IEnumerable<ErrorMessage> messages)
{
var result = new Result<T>();
result.Success = false;
result.Errors = messages;
return result;
}
}
public class Result<T> : Result
{
public T Value { get; set; }
}
public class ErrorMessage
{
public string PropertyName { get; set; }
public string Message { get; set; }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment