Base solution for your next web application

Activities of "nikko"

Does anyone know a better solution?

Sure:

public override void Up()
        {
            DropIndex("dbo.NotificationSubscriptions", new[] { "NotificationName", "EntityTypeName", "EntityId", "UserId" });
            DropIndex("dbo.UserLoginAttempts", new[] { "TenancyName", "UserNameOrEmailAddress", "Result" });
            AlterColumn("dbo.AuditLogs", "ServiceName", c => c.String(maxLength: 256, unicode: false));
            AlterColumn("dbo.AuditLogs", "MethodName", c => c.String(maxLength: 256, unicode: false));
            AlterColumn("dbo.AuditLogs", "Parameters", c => c.String(maxLength: 1024, unicode: false));
            AlterColumn("dbo.AuditLogs", "ClientIpAddress", c => c.String(maxLength: 64, unicode: false));
            AlterColumn("dbo.AuditLogs", "ClientName", c => c.String(maxLength: 128, unicode: false));
            AlterColumn("dbo.AuditLogs", "BrowserInfo", c => c.String(maxLength: 256, unicode: false));
            AlterColumn("dbo.AuditLogs", "Exception", c => c.String(maxLength: 2000, unicode: false));
            AlterColumn("dbo.AuditLogs", "CustomData", c => c.String(maxLength: 2000, unicode: false));
            AlterColumn("dbo.BackgroundJobs", "JobType", c => c.String(nullable: false, maxLength: 512, unicode: false));
            AlterColumn("dbo.BackgroundJobs", "JobArgs", c => c.String(nullable: false, unicode: false));
            AlterColumn("dbo.Features", "Name", c => c.String(nullable: false, maxLength: 128, unicode: false));
            AlterColumn("dbo.Features", "Value", c => c.String(nullable: false, maxLength: 2000, unicode: false));
            AlterColumn("dbo.Editions", "Name", c => c.String(nullable: false, maxLength: 32, unicode: false));
            AlterColumn("dbo.Editions", "DisplayName", c => c.String(nullable: false, maxLength: 64, unicode: false));
            AlterColumn("dbo.Languages", "Name", c => c.String(nullable: false, maxLength: 10, unicode: false));
            AlterColumn("dbo.Languages", "DisplayName", c => c.String(nullable: false, maxLength: 64, unicode: false));
            AlterColumn("dbo.Languages", "Icon", c => c.String(maxLength: 128, unicode: false));
            AlterColumn("dbo.LanguageTexts", "LanguageName", c => c.String(nullable: false, maxLength: 10, unicode: false));
            AlterColumn("dbo.LanguageTexts", "Source", c => c.String(nullable: false, maxLength: 128, unicode: false));
            AlterColumn("dbo.LanguageTexts", "Key", c => c.String(nullable: false, maxLength: 256, unicode: false));
            AlterColumn("dbo.LanguageTexts", "Value", c => c.String(nullable: false, unicode: false));
            AlterColumn("dbo.Notifications", "NotificationName", c => c.String(nullable: false, maxLength: 96, unicode: false));
            AlterColumn("dbo.Notifications", "Data", c => c.String(unicode: false));
            AlterColumn("dbo.Notifications", "DataTypeName", c => c.String(maxLength: 512, unicode: false));
            AlterColumn("dbo.Notifications", "EntityTypeName", c => c.String(maxLength: 250, unicode: false));
            AlterColumn("dbo.Notifications", "EntityTypeAssemblyQualifiedName", c => c.String(maxLength: 512, unicode: false));
            AlterColumn("dbo.Notifications", "EntityId", c => c.String(maxLength: 96, unicode: false));
            AlterColumn("dbo.Notifications", "UserIds", c => c.String(unicode: false));
            AlterColumn("dbo.Notifications", "ExcludedUserIds", c => c.String(unicode: false));
            AlterColumn("dbo.Notifications", "TenantIds", c => c.String(unicode: false));
            AlterColumn("dbo.NotificationSubscriptions", "NotificationName", c => c.String(maxLength: 96, unicode: false));
            AlterColumn("dbo.NotificationSubscriptions", "EntityTypeName", c => c.String(maxLength: 250, unicode: false));
            AlterColumn("dbo.NotificationSubscriptions", "EntityTypeAssemblyQualifiedName", c => c.String(maxLength: 512, unicode: false));
            AlterColumn("dbo.NotificationSubscriptions", "EntityId", c => c.String(maxLength: 96, unicode: false));
            AlterColumn("dbo.OrganizationUnits", "Code", c => c.String(nullable: false, maxLength: 128, unicode: false));
            AlterColumn("dbo.OrganizationUnits", "DisplayName", c => c.String(nullable: false, maxLength: 128, unicode: false));
            AlterColumn("dbo.Permissions", "Name", c => c.String(nullable: false, maxLength: 128, unicode: false));
            AlterColumn("dbo.Roles", "DisplayName", c => c.String(nullable: false, maxLength: 64, unicode: false));
            AlterColumn("dbo.Roles", "Name", c => c.String(nullable: false, maxLength: 32, unicode: false));
            AlterColumn("dbo.Users", "AuthenticationSource", c => c.String(maxLength: 64, unicode: false));
            AlterColumn("dbo.Users", "Name", c => c.String(nullable: false, maxLength: 32, unicode: false));
            AlterColumn("dbo.Users", "Surname", c => c.String(nullable: false, maxLength: 32, unicode: false));
            AlterColumn("dbo.Users", "Password", c => c.String(nullable: false, maxLength: 128, unicode: false));
            AlterColumn("dbo.Users", "EmailConfirmationCode", c => c.String(maxLength: 128, unicode: false));
            AlterColumn("dbo.Users", "PasswordResetCode", c => c.String(maxLength: 328, unicode: false));
            AlterColumn("dbo.Users", "UserName", c => c.String(nullable: false, maxLength: 32, unicode: false));
            AlterColumn("dbo.Users", "EmailAddress", c => c.String(nullable: false, maxLength: 256, unicode: false));
            AlterColumn("dbo.UserLogins", "LoginProvider", c => c.String(nullable: false, maxLength: 128, unicode: false));
            AlterColumn("dbo.UserLogins", "ProviderKey", c => c.String(nullable: false, maxLength: 256, unicode: false));
            AlterColumn("dbo.Settings", "Name", c => c.String(nullable: false, maxLength: 256, unicode: false));
            AlterColumn("dbo.Settings", "Value", c => c.String(maxLength: 2000, unicode: false));
            AlterColumn("dbo.TenantNotifications", "NotificationName", c => c.String(nullable: false, maxLength: 96, unicode: false));
            AlterColumn("dbo.TenantNotifications", "Data", c => c.String(unicode: false));
            AlterColumn("dbo.TenantNotifications", "DataTypeName", c => c.String(maxLength: 512, unicode: false));
            AlterColumn("dbo.TenantNotifications", "EntityTypeName", c => c.String(maxLength: 250, unicode: false));
            AlterColumn("dbo.TenantNotifications", "EntityTypeAssemblyQualifiedName", c => c.String(maxLength: 512, unicode: false));
            AlterColumn("dbo.TenantNotifications", "EntityId", c => c.String(maxLength: 96, unicode: false));
            AlterColumn("dbo.Tenants", "Name", c => c.String(nullable: false, maxLength: 128, unicode: false));
            AlterColumn("dbo.Tenants", "TenancyName", c => c.String(nullable: false, maxLength: 64, unicode: false));
            AlterColumn("dbo.Tenants", "ConnectionString", c => c.String(maxLength: 1024, unicode: false));
            AlterColumn("dbo.UserAccounts", "UserName", c => c.String(unicode: false));
            AlterColumn("dbo.UserAccounts", "EmailAddress", c => c.String(unicode: false));
            AlterColumn("dbo.UserLoginAttempts", "TenancyName", c => c.String(maxLength: 64, unicode: false));
            AlterColumn("dbo.UserLoginAttempts", "UserNameOrEmailAddress", c => c.String(maxLength: 255, unicode: false));
            AlterColumn("dbo.UserLoginAttempts", "ClientIpAddress", c => c.String(maxLength: 64, unicode: false));
            AlterColumn("dbo.UserLoginAttempts", "ClientName", c => c.String(maxLength: 128, unicode: false));
            AlterColumn("dbo.UserLoginAttempts", "BrowserInfo", c => c.String(maxLength: 256, unicode: false));
            CreateIndex("dbo.NotificationSubscriptions", new[] { "NotificationName", "EntityTypeName", "EntityId", "UserId" });
            CreateIndex("dbo.UserLoginAttempts", new[] { "TenancyName", "UserNameOrEmailAddress", "Result" });
        }
        
        public override void Down()
        {
            DropIndex("dbo.UserLoginAttempts", new[] { "TenancyName", "UserNameOrEmailAddress", "Result" });
            DropIndex("dbo.NotificationSubscriptions", new[] { "NotificationName", "EntityTypeName", "EntityId", "UserId" });
            AlterColumn("dbo.UserLoginAttempts", "BrowserInfo", c => c.String(maxLength: 256));
            AlterColumn("dbo.UserLoginAttempts", "ClientName", c => c.String(maxLength: 128));
            AlterColumn("dbo.UserLoginAttempts", "ClientIpAddress", c => c.String(maxLength: 64));
            AlterColumn("dbo.UserLoginAttempts", "UserNameOrEmailAddress", c => c.String(maxLength: 255));
            AlterColumn("dbo.UserLoginAttempts", "TenancyName", c => c.String(maxLength: 64));
            AlterColumn("dbo.UserAccounts", "EmailAddress", c => c.String());
            AlterColumn("dbo.UserAccounts", "UserName", c => c.String());
            AlterColumn("dbo.Tenants", "ConnectionString", c => c.String(maxLength: 1024));
            AlterColumn("dbo.Tenants", "TenancyName", c => c.String(nullable: false, maxLength: 64));
            AlterColumn("dbo.Tenants", "Name", c => c.String(nullable: false, maxLength: 128));
            AlterColumn("dbo.TenantNotifications", "EntityId", c => c.String(maxLength: 96));
            AlterColumn("dbo.TenantNotifications", "EntityTypeAssemblyQualifiedName", c => c.String(maxLength: 512));
            AlterColumn("dbo.TenantNotifications", "EntityTypeName", c => c.String(maxLength: 250));
            AlterColumn("dbo.TenantNotifications", "DataTypeName", c => c.String(maxLength: 512));
            AlterColumn("dbo.TenantNotifications", "Data", c => c.String());
            AlterColumn("dbo.TenantNotifications", "NotificationName", c => c.String(nullable: false, maxLength: 96));
            AlterColumn("dbo.Settings", "Value", c => c.String(maxLength: 2000));
            AlterColumn("dbo.Settings", "Name", c => c.String(nullable: false, maxLength: 256));
            AlterColumn("dbo.UserLogins", "ProviderKey", c => c.String(nullable: false, maxLength: 256));
            AlterColumn("dbo.UserLogins", "LoginProvider", c => c.String(nullable: false, maxLength: 128));
            AlterColumn("dbo.Users", "EmailAddress", c => c.String(nullable: false, maxLength: 256));
            AlterColumn("dbo.Users", "UserName", c => c.String(nullable: false, maxLength: 32));
            AlterColumn("dbo.Users", "PasswordResetCode", c => c.String(maxLength: 328));
            AlterColumn("dbo.Users", "EmailConfirmationCode", c => c.String(maxLength: 128));
            AlterColumn("dbo.Users", "Password", c => c.String(nullable: false, maxLength: 128));
            AlterColumn("dbo.Users", "Surname", c => c.String(nullable: false, maxLength: 32));
            AlterColumn("dbo.Users", "Name", c => c.String(nullable: false, maxLength: 32));
            AlterColumn("dbo.Users", "AuthenticationSource", c => c.String(maxLength: 64));
            AlterColumn("dbo.Roles", "Name", c => c.String(nullable: false, maxLength: 32));
            AlterColumn("dbo.Roles", "DisplayName", c => c.String(nullable: false, maxLength: 64));
            AlterColumn("dbo.Permissions", "Name", c => c.String(nullable: false, maxLength: 128));
            AlterColumn("dbo.OrganizationUnits", "DisplayName", c => c.String(nullable: false, maxLength: 128));
            AlterColumn("dbo.OrganizationUnits", "Code", c => c.String(nullable: false, maxLength: 128));
            AlterColumn("dbo.NotificationSubscriptions", "EntityId", c => c.String(maxLength: 96));
            AlterColumn("dbo.NotificationSubscriptions", "EntityTypeAssemblyQualifiedName", c => c.String(maxLength: 512));
            AlterColumn("dbo.NotificationSubscriptions", "EntityTypeName", c => c.String(maxLength: 250));
            AlterColumn("dbo.NotificationSubscriptions", "NotificationName", c => c.String(maxLength: 96));
            AlterColumn("dbo.Notifications", "TenantIds", c => c.String());
            AlterColumn("dbo.Notifications", "ExcludedUserIds", c => c.String());
            AlterColumn("dbo.Notifications", "UserIds", c => c.String());
            AlterColumn("dbo.Notifications", "EntityId", c => c.String(maxLength: 96));
            AlterColumn("dbo.Notifications", "EntityTypeAssemblyQualifiedName", c => c.String(maxLength: 512));
            AlterColumn("dbo.Notifications", "EntityTypeName", c => c.String(maxLength: 250));
            AlterColumn("dbo.Notifications", "DataTypeName", c => c.String(maxLength: 512));
            AlterColumn("dbo.Notifications", "Data", c => c.String());
            AlterColumn("dbo.Notifications", "NotificationName", c => c.String(nullable: false, maxLength: 96));
            AlterColumn("dbo.LanguageTexts", "Value", c => c.String(nullable: false));
            AlterColumn("dbo.LanguageTexts", "Key", c => c.String(nullable: false, maxLength: 256));
            AlterColumn("dbo.LanguageTexts", "Source", c => c.String(nullable: false, maxLength: 128));
            AlterColumn("dbo.LanguageTexts", "LanguageName", c => c.String(nullable: false, maxLength: 10));
            AlterColumn("dbo.Languages", "Icon", c => c.String(maxLength: 128));
            AlterColumn("dbo.Languages", "DisplayName", c => c.String(nullable: false, maxLength: 64));
            AlterColumn("dbo.Languages", "Name", c => c.String(nullable: false, maxLength: 10));
            AlterColumn("dbo.Editions", "DisplayName", c => c.String(nullable: false, maxLength: 64));
            AlterColumn("dbo.Editions", "Name", c => c.String(nullable: false, maxLength: 32));
            AlterColumn("dbo.Features", "Value", c => c.String(nullable: false, maxLength: 2000));
            AlterColumn("dbo.Features", "Name", c => c.String(nullable: false, maxLength: 128));
            AlterColumn("dbo.BackgroundJobs", "JobArgs", c => c.String(nullable: false));
            AlterColumn("dbo.BackgroundJobs", "JobType", c => c.String(nullable: false, maxLength: 512));
            AlterColumn("dbo.AuditLogs", "CustomData", c => c.String(maxLength: 2000));
            AlterColumn("dbo.AuditLogs", "Exception", c => c.String(maxLength: 2000));
            AlterColumn("dbo.AuditLogs", "BrowserInfo", c => c.String(maxLength: 256));
            AlterColumn("dbo.AuditLogs", "ClientName", c => c.String(maxLength: 128));
            AlterColumn("dbo.AuditLogs", "ClientIpAddress", c => c.String(maxLength: 64));
            AlterColumn("dbo.AuditLogs", "Parameters", c => c.String(maxLength: 1024));
            AlterColumn("dbo.AuditLogs", "MethodName", c => c.String(maxLength: 256));
            AlterColumn("dbo.AuditLogs", "ServiceName", c => c.String(maxLength: 256));
            CreateIndex("dbo.UserLoginAttempts", new[] { "TenancyName", "UserNameOrEmailAddress", "Result" });
            CreateIndex("dbo.NotificationSubscriptions", new[] { "NotificationName", "EntityTypeName", "EntityId", "UserId" });
        }

Anyway, if we cannot change like this, is there another way? Unicode columns take twice the space if compared to non-unicode.

I want to change column datatype. For example I don't need all the columns to be nvarchar and also I think 256 is too much for an e-mail column. What would be the best way of achieving this?

I tried to override OnModelCreating with:

base.OnModelCreating(modelBuilder); modelBuilder.ChangeAbpTablePrefix<Tenant, Role, User>(""); modelBuilder.Properties<string>().Configure(p => p.IsUnicode(false));

But I get this error when trying to update the database:

The index 'IX_Discriminator_TenantId_Name' is dependent on column 'Name'. The index 'IX_Discriminator_EditionId_Name' is dependent on column 'Name'. The index 'IX_TenantId_Name' is dependent on column 'Name'. ALTER TABLE ALTER COLUMN Name failed because one or more objects access this column.

Any ideas?

I am developing a single tenant application. Users can buy subscriptions and they have different features and permissions. For example

Basic - cant send emails. Intermediate - can send 10 emails. Advanced - can send 30 emails.

From my understanding I cannot assign editions directly to users. What would be the best way to implement this in ABP? Should i create Roles like basic, intermediate and adanced and assign to the users and assign permissions to the Roles? The problem with permissions is that basic does not have and intermediate and advanced have but how do I control the amount of emails they can send?

Thanks.

Hello!

I've tested it and it kind of works. I modified the code a bit just to compile:

public static class ModelStateExtensions
    {
        public static MvcAjaxResponse ToMvcAjaxResponse(ModelStateDictionary modelState)
        {
            var validationErrors = new List<ValidationErrorInfo>();

            foreach (var state in modelState)
            {
                foreach (var error in state.Value.Errors)
                {
                    validationErrors.Add(new ValidationErrorInfo(error.ErrorMessage, new[] { state.Key }));
                }
            }

            var errorInfo = new ErrorInfo("test")
            {
                ValidationErrors = validationErrors.ToArray()
            };

            return new MvcAjaxResponse(errorInfo);
        }
    }

Then i added some modelstate errors like:

ModelState.AddModelError("Field1", "Field1 Invalid!");
ModelState.AddModelError("", "Field Withname invalid!");

The JSON that i get back looks like:

{
  "targetUrl": null,
  "success": false,
  "result": null,
  "error": {
    "code": 0,
    "message": "test",
    "details": null,
    "validationErrors": [
      {
        "message": "Field1 Invalid!",
        "members": [
          "Field1"
        ]
      },
      {
        "message": "Field Withname invalid!",
        "members": [
          ""
        ]
      }
    ]
  },
  "unAuthorizedRequest": false
}

My question is how do i get validationErrors from the JSON when i need to override abp.message.error:

abp.message.error = function(message, title) {
    // need to add my code to show the errors the way i want.
}

Thanks!

Hello!

I like to maintain the same feel of client and server validation errors when displaying it to the user. Usually i use the mvc built-in helpers to build the errors for me (ValidationSummary and ValidationFor). When the request gets to the controller if it's a regular post there's no problem we just do:

if (!ModelState.IsValid()) 
{
 return View();
}

And the errors get displayed. The 'problem' starts when we use an AJAX request. Today what i do is read the errors from the ModelState and build a JSON that is returned to the client. Then using jquery i add the errors to the generated html of ValidationSummary and ValidationFor.

I noticed that when a validation error occurs we should use UserFriendlyException. Then i could just implement abp.message.error in the client and it will be done. But the thing is that i can only return one error to the client using this exception. What if i have more errors on my modelstate from multiple properties? Is there anyway to solve this? Also is there a built-in way convert the modelstate errors to this exception?

Thank you for your effort on this project it's really awesome!

Showing 1 to 6 of 6 entries