You passed wrong values to your service method that does not respect the rules you defined.
On server side you can do more things:
1- trace your call and catch the AbpValidationException
try {
...
} catch(AbpValidationException ex) {
var string = ex.ValidationErrors
.Select(err => err.ToString())
.Aggregate(string.Empty, (current, next) => string.Format("{0}\n{1}", current, next));
}
Another solution is to edit your Dto input and implement the ICustomValidate.
For example:
public class AddBidInput : ICustomValidate, IMyDto {
public long AuctionId { get; set; }
...
public virtual void AddValidationErrors(CustomValidationContext context) {
var results = context.Results;
if (AuctionId <= 0) {
results.Add(new ValidationResult("auction id cannot be <= 0", new[] { "AuctionId" }));
}
}
}
<cite>zokho: </cite> Hi, Does anyone know that if its feasible to upload files using Dtos in the Application layer? If yes, can I have a sample code which shows how to define properties in DTO classes and how to call the service from AngularJS?
This is the same issue I have!
I really don't know where to start. Does anybody have a working example with ABP, AngularJs page and an Application Service or an AbpApiController?
Please, help! Gp
<cite>kaushikthanki: </cite> any solution for server side ? I have successfully implemented on client end,
try these 2 links
<a class="postlink" href="http://blog.dmbcllc.com/asp-net-angular-js-html5mode/">http://blog.dmbcllc.com/asp-net-angular-js-html5mode/</a> <a class="postlink" href="https://github.com/angular-ui/ui-router/wiki/Frequently-Asked-Questions#how-to-configure-your-server-to-work-with-html5mode">https://github.com/angular-ui/ui-router ... -html5mode</a>
override the LoginAsync method and throw an exception if you do not find the user via username. If you find it, call the base LoginAsync method.
I did not test it but it'd be something like this:
[UnitOfWork]
public override async Task<AbpLoginResult<Tenant, User>> LoginAsync(string userNameOrEmailAddress, string plainPassword, string tenancyName = null, bool shouldLockout = true) {
// this method search for the user by checking just the username field, not the emailaddress fiel.
// In this way, if the user passes the email address the method fails throwing an ex.
var user = await this.UserManager.FindByNameAsync(userNameOrEmailAddress);
// if you are here, the username is OK
return await base.LoginAsync(userNameOrEmailAddress, plainPassword, tenancyName, shouldLockout);
}
Which version of EntityFramework.DynamicFilters are you using? It has to be 1.4.11, not newer.
Default token expiration should be to 20 minutes, due to the fact the OAuth2 authorization server discards it, even if you try to set it.
A work around is to set the expiration date in AuthenticationTokenProvider.CreateAsync (the class you use for OAuthAuthorizationServerOptions.AccessTokenProvider). Set context.Ticket.Properties.ExpiresUtc with the expiration date of your choice, and it should work: Try to see: <a class="postlink" href="http://stackoverflow.com/questions/33701398/oauth2-webapi-token-expiration">http://stackoverflow.com/questions/3370 ... expiration</a>.
See AbpLogInManager AbpSignInManager
Why you say "It is bad to let one appservice use another appservice"?
Anyhow, I put some of this code in MyAppServiceBase, Some in Manager classes and some in Helpers:
public class AuctionAppService : MyNewHouseAppServiceBase, IAuctionAppService {
private readonly IAuctionRepo _auctionsRepo;
public UserManager UserManager { get; set; }
...
}
public abstract class MyNewHouseAppServiceBase : ApplicationService {
public TenantManager TenantManager { get; set; }
public IEventBus EventBus { get; set; }
protected async virtual Task<User> MyCommonUsefulMethodAsync(...) {
...
return user;
}
...
}
public class UserManager : AbpUserManager<Role, User> {
public UserManager(
UserStore userStore,
RoleManager roleManager,
IPermissionManager permissionManager,
IUnitOfWorkManager unitOfWorkManager,
ICacheManager cacheManager,
IRepository<OrganizationUnit, long> organizationUnitRepository,
IRepository<UserOrganizationUnit, long> userOrganizationUnitRepository,
IOrganizationUnitSettings organizationUnitSettings,
ILocalizationManager localizationManager,
ISettingManager settingManager,
IdentityEmailMessageService emailService,
IUserTokenProviderAccessor userTokenProviderAccessor)
: base(
userStore,
roleManager,
permissionManager,
unitOfWorkManager,
cacheManager,
organizationUnitRepository,
userOrganizationUnitRepository,
organizationUnitSettings,
localizationManager,
emailService,
settingManager,
userTokenProviderAccessor) {
}
...
}
Use filters:
public async Task<PagedResultDto<SimpleUserDto>> FindByMyCriteriaSimple(SearchInputBasic input) {
IDisposable filter = null;
try {
filter = _unitOfWorkManager.Current.DisableFilter(true);
// now your query returns 'soft deleted' items too
var users = await _userRepository.FindByMyCriteriaAsync(input.Pattern, input.SkipCount, input.MaxResultCount);
. . .
return ...;
}
finally {
if (filter != null) filter.Dispose();
}
}
See <a class="postlink" href="http://www.aspnetboilerplate.com/Pages/Documents/Data-Filters#DocDisableFilters">http://www.aspnetboilerplate.com/Pages/ ... bleFilters</a>
Some code:
This is your new entity (place it somewhere in YourProject.Core project):
[Table("ReBid")]
public class Bid : FullAuditedEntity<long> {
public Bid() {
CreationTime = Clock.Now;
}
[DataType(DataType.Currency)]
[Column(TypeName = "money")]
[Range(0, double.MaxValue)]
public decimal Amount { get; set; }
public long RegistrationId { get; set; }
[ForeignKey("RegistrationId")]
public virtual BidderRegistration Registration { get; set; }
/// <summary>True if this is the winning bid of an auction</summary>
public bool IsWinner { get; set; }
}
Then add the proper IDbSet in the DbContext class you find in YourProject.EntityFramework project:
public class YourProjectDbContext : AbpZeroDbContext<Tenant, Role, User> {
...
public virtual IDbSet<Bid> Bids { get; set; }
...
}
What do you mean?
Would you like to read data from a repository and copy them to your main repo to be seed, or what?