I have a web api created in .Net Core 2.2, I added the swagger and it is working perfectly, but I want to make some customizations in the documentation.
I have some viewsmodels that I use is the same to receive the request as for the response, so Swagger displays some properties that are not required in the post, as example below:
public class RegisterViewModel
{
[Required]
public string Name { get; set; }
[Required]
[EmailAddress]
[Display(Name = "Email")]
public string Email { get; set; }
[Required]
[DataType(DataType.Password)]
public string Password { get; set; }
public string TokenJWT { get; set; }
}
In Swagger when I did the test for the post displays TokenJWT, but in the post this is not required, I do not want it to be displayed, after the post successfully returned the same viewmodel informing the generated token, so the property exists. How to do this without creating a viewmodel for request and another for response?
Related
Asp.net core server side localization is well documented and working for me. But how do you localize DataAnnotations on DTO models on the client side of Blazor webassembly?
On server side I've added the code below and DataAnnotations are localized. Everything is working as expected.
...
services
.AddRazorPages() .AddViewLocalization(Microsoft.AspNetCore.Mvc.Razor.LanguageViewLocationExpanderFormat.Suffix)
.AddDataAnnotationsLocalization(
options =>
{
options.DataAnnotationLocalizerProvider = (type, factory) =>
{
return factory.Create(typeof(CommonStrings));
};
});
...
But how do I do the same thing on Blazor client side (webassembly)?
For example I have this model which is on client side:
public class ApplicationUserDTO
{
public string Id { get; set; }
[Required(ErrorMessage ="Field {0} is required")]
[Display(Name ="First name")]
public string FirstName { get; set; }
[Required]
[Display(Name = "Last name")]
public string LastName { get; set; }
[Required]
[Display(Name = "Email")]
public string Email { get; set; }
[Required]
[Display(Name = "Username")]
public string Username { get; set; }
}
I want to post it to backend via <EditForm> component, and before I do that do the validation on client side.
I also want to localize it like i would on aspnet.core server - Error/validation messages and display names...
I tried with LocalizedValidator component:
public class MessageValidatorBase<TValue> : ComponentBase, IDisposable
{
private FieldIdentifier _fieldIdentifier;
private EventHandler<ValidationStateChangedEventArgs> _stateChangedHandler
=> (sender, args) => StateHasChanged();
[CascadingParameter]
private EditContext EditContext { get; set; }
[Parameter]
public Expression<Func<TValue>> For { get; set; }
[Parameter]
public string Class { get; set; }
protected IEnumerable<string> ValidationMessages =>
EditContext.GetValidationMessages(_fieldIdentifier);
protected override void OnInitialized()
{
_fieldIdentifier = FieldIdentifier.Create(For);
EditContext.OnValidationStateChanged += _stateChangedHandler;
}
public void Dispose()
{
EditContext.OnValidationStateChanged -= _stateChangedHandler;
}
}
and then created component:
#typeparam TValue
#inherits MessageValidatorBase<TValue>
#inject StringLocalizationService _localizer
#foreach (var message in ValidationMessages)
{
<div class="#Class">
#_localizer[message]
</div>
}
but the problem is I get already expanded string here. For example if I have error message like this "The field {0} is required" I get "The field First name is required" which will not be localized since I don't have the resource with that key and I don't intend to translate the same error message for every property name...
[EDIT]
I just want to know if there is something trivial I didn't do instead of implementing it completely on my own
WebAssembly example.
Example property
[MaxLength(5, ErrorMessageResourceName = "LengthError", ErrorMessageResourceType = typeof(Resources.App))]
public string Prefix { get; set; }
Create a folder in your client called Resources.
Add a `.resx' file for each language plus a default (no language).
Make sure your set the access Modifier to Public
Example output in French.
I am getting an error
Validation failed for one or more entities. See 'EntityValidationErrors' property for more details.
when trying to submit on a simple create page. Below is the controller code and model. I can not figure out what the issue is.
All fields except ID are nullable in SQL. I know that the issue is coming from the fields resolution and technician - if I put them on the create form (which they are not on it now as I do not want them filled out) the submit works fine Any ideas?
Thanks,
EB
Controller:
public ActionResult Create()
{
HelpDesk b1 = new HelpDesk();
return View(b1);
}
[HttpPost]
public ActionResult Create(HelpDesk model)
{
db.HelpDesks.Add(model);
db.SaveChanges();
return RedirectToAction("Index");
}
Model:
public int ID { get; set; }
[DisplayName("Requested By")]
public string RequestedBy { get; set; }
[Required(ErrorMessage = "Requested By Required.")]
public string Request { get; set; }
[Required(ErrorMessage = "Request Required.")]
public string Resolution { get; set; }
[DisplayName("Assigned To")]
public string Technician { get; set; }
public string Status { get; set; }
public string CreatedBy { get; set; }
public string ModfiedBy { get; set; }
public Nullable<System.DateTime> CreateDate { get; set; }
public Nullable<System.DateTime> ModifiedDate { get; set; }
All fields except ID is nullable in SQL.
That's not what you told Entity Framework, which is what's throwing the error. (And, as the error indicates, you should really check the EntityValidationErrors property on the exception, or an inner exception, for specific information about the error.) You told Entity Framework that these fields are required:
[Required(ErrorMessage = "Requested By Required.")]
public string Request { get; set; }
[Required(ErrorMessage = "Request Required.")]
public string Resolution { get; set; }
(It looks like you may have mixed up some of the property attributes, judging by the messages on them.)
I know that the issue is coming from the fields resolution and technician - if I put them on the create form (which they are not on it now as I do not want them filled out) the submit works fine
Sounds like that's the problem then. Resolution is marked as required, and you're not including it. Either include it or don't make it required.
So I am creating a an API with ASP.net MVC Web API. I currently have a model which contains the fields for a user in the database. I have a password field on this model. See below for an example.
public class Account
{
[Key]
public Guid UserId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string UserName { get; set; }
public string Email { get; set; }
public string Password { get; set; }
}
I return this model using JSON when a controller method is called over HTTP. This works fine.
My question is, how do I stop the password field being returned alongside with it? Without removing the field altogether.
My initial idea is to create another model class which I use to return the data without the password field, but I'd rather not repeat myself for the sake of one field.
Any suggestions?
You should be able to mark these fields with
[JsonIgnore]
[XmlIgnore]
public string Password { get; set; }
Preventing these fields to be used in either JSON or XML requests.
I use the Durandal template in my asp.net mvc solution. The question here is related to Breeze which is also used in Durandal. Let's say I have the following entity in my model:
public class Driver
{
[Key]
public int Id { get; set; }
[Required]
public string Firstname { get; set; }
[Required]
public string Lastname { get; set; }
public string Comment { get; set; }
public int? CreatedById { get; set; }
public DateTime? CreatedTime { get; set; }
public int? UpdatedById { get; set; }
public DateTime? UpdatedTime { get; set; }
public virtual User CreatedBy { get; set; }
public virtual User UpdatedBy { get; set; }
}
As you can see, I have some properties used to track creation/updates for time and userid (UpdatedById, UpdatedTime, ...). I would like to let the user edit/create my drivers in some data entry pages then fill in these properties (UpdatedById, UpdatedTime, ...) server side automatically in the BeforeSaveEntity method.
It works but as you noted I had to allow nullable on the properties like int? or DateTime? because in case of adding a new entity (everything is blank) the validation failed if I didn't proceed like that.
My question: is there another solution or something that could be done to avoid using nullable types on my model (int? - DateTime?) for these properties which track my creation/edition?
Thanks.
Make them nonnullable and fill in "dummy" values of the client, in a "registered" ctor for each type that will then get overwritten on the server.
I'm trying to make Json .NET Ignore a property by using the Json Ignore Attribute when clients GET the object but I want to be able to receive that property when a client is POST'ing
In example I have:
When the client POSTs data, password should be sent:
{"email":"email#domain.com","password":"P#ssW0rd1!","firstname":"Joe","lastname":"Doe"}
However, when the client GETs the same object, I should Ignore the Password:
{"email":"email#domain.com","firstname":"Joe","lastname":"Doe"}
Class:
public class User
{
public User()
{
this.JoinDate = DateTime.UtcNow;
this.IsActive = false;
}
public int Id { get; set; }
[Required(ErrorMessage = "Email is required!")]
public string Email { get; set; }
[JsonIgnore]
public string HashedPassword { get; set; }
[Required(ErrorMessage = "Password is required!")]
public string Password { get; set; }
public DateTime JoinDate { get; set; }
[Required(ErrorMessage = "First Name is required!")]
public string FirstName { get; set; }
[Required(ErrorMessage = "Last Name is required!")]
public string LastName { get; set; }
}
Any ideas, suggestions, comments???
In your scenario here, I would recommend you to split your User class into 2 separate model classes:
Login class, which has the login information (i.e. Email, Password)
UserInfo class, which has the rest of the metadata about the User (i.e. FirstName, LastName)
This way, we are not depending on the serializer to hide sensitive data.
You could use [IgnoreDataMember] attributes and the out-of-box XML and JSON formatters will support them, but there is no guarantee that any other custom formatter registered will support it.
Note that [JsonIgnore] is only supported in the JSON formatter but not the XML formatter.