Issue: How to trim text using asp-for
tag & razor page?
Detail: I have a input field where user can enter there firstname
. I noticed user can enter multi spaces or tabs. Since I am using asp-for
tag, it will auto bind the data to Person
object on OnPost()
Method
I am trying not to use following methods Request.Form("firstname").trim()
or pass value though OnPost(string firstname)
Method; Because whole point of asp-for
tag is to auto bind your values to object rather than manually getting each values like using name
tag.
If there isn't any way to do this, than what is the point of asp.for
tag? bc in real world you will end up checking for extra spaces any ways.
<input asp-for="Person.FirstName" />
<span asp-validation-for="Person.FirstName" class="text-danger"></span>
[BindProperty]
public Person_Model Person { get; set; } = default!;
[BindProperty(SupportsGet = true)]
public string? FirstName{ get; set; }
public async Task<IActionResult> OnPostAsync()
{
// here First_name can have spaces
_context2.my_DbSet.Add(Person);
await _context2.SaveChangesAsync();
}
public class Person_Model
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public Int64 Id { get; set; }
public string? FirstName{ get; set; }
}
I tried adding RegularExpression, but this will just give me error if there is whtie space inside text-field. I just want to trim it.
[RegularExpression(@"[^\s]+")]
public string? FirstName{ get; set; }
The recommended method for centralising trimming of input strings is to create a custom model binder which does this as part of the model binding process.
Create a class called TrimModelBinder:
public class TrimModelBinder : IModelBinder
{
public Task BindModelAsync(ModelBindingContext bindingContext)
{
var valueProviderResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
if (valueProviderResult != ValueProviderResult.None)
{
bindingContext.Result = ModelBindingResult.Success(valueProviderResult.FirstValue?.Trim());
}
return Task.CompletedTask;
}
}
Create a ModelBinderProvider that returns your new model binder if the binding target is a string:
public class TrimModelBinderProvider : IModelBinderProvider
{
public IModelBinder GetBinder(ModelBinderProviderContext context)
{
if (context.Metadata.ModelType == typeof(string))
{
return new BinderTypeModelBinder(typeof(TrimModelBinder));
}
return null;
}
}
Register this with the services container:
builder.Services.AddMvc(options => options.ModelBinderProviders.Insert(0, new TrimModelBinderProvider()));
Now you no longer have to call Trim()
on every input string.