Skip to content
This repository was archived by the owner on May 10, 2020. It is now read-only.

Commit c1146fc

Browse files
committed
Validations
1 parent 22de520 commit c1146fc

File tree

8 files changed

+127
-4
lines changed

8 files changed

+127
-4
lines changed

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,10 @@ As you can see in the example above BlazorDB will detect associations added to t
163163

164164
**Note:** At this time removing/deleting is not done automatically and needs to be done manually. A future update of BlazorDB will handle deletions properly.
165165

166+
## Validations
167+
168+
You can annotate your model's propeties with `[Required]` and `[MaxLength(int)]` to enforce required and max length on properties.
169+
166170
## Example
167171

168172
A Todo sample built with BlazorDB is included in the sample project:

src/BlazorDB/BlazorDB.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
<BlazorLinkOnBuild>false</BlazorLinkOnBuild>
88
<LangVersion>7.3</LangVersion>
99
<PackageId>BlazorDB</PackageId>
10-
<Version>0.1.2</Version>
10+
<Version>0.1.3</Version>
1111
<Authors>Chanan Braunstein</Authors>
1212
<Title>Blazor localStorage Database</Title>
1313
<Description>In memory, persisted to localstorage, database for .net Blazor browser framework</Description>
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
using System;
2+
3+
namespace BlazorDB
4+
{
5+
public class BlazorDBUpdateException : Exception
6+
{
7+
public BlazorDBUpdateException(string error) : base(error)
8+
{
9+
}
10+
}
11+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
using System;
2+
3+
namespace BlazorDB.DataAnnotations
4+
{
5+
[AttributeUsage(AttributeTargets.Property)]
6+
public class MaxLength : Attribute
7+
{
8+
public MaxLength(int length)
9+
{
10+
this.length = length;
11+
}
12+
13+
internal int length;
14+
}
15+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
using System;
2+
3+
namespace BlazorDB.DataAnnotations
4+
{
5+
[AttributeUsage(AttributeTargets.Property)]
6+
public class Required : Attribute
7+
{
8+
}
9+
}

src/BlazorDB/Storage/StorageManagerSave.cs

Lines changed: 65 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using System.Collections.Generic;
44
using System.Linq;
55
using System.Reflection;
6+
using BlazorDB.DataAnnotations;
67
using Microsoft.AspNetCore.Blazor;
78

89
namespace BlazorDB.Storage
@@ -15,12 +16,73 @@ public int SaveContextToLocalStorage(StorageContext context)
1516
var contextType = context.GetType();
1617
Logger.ContextSaved(contextType);
1718
var storageSets = StorageManagerUtil.GetStorageSets(contextType);
18-
var metadataMap = LoadMetadataList(context, storageSets, contextType);
19-
total = SaveStorageSets(context, total, contextType, storageSets, metadataMap);
20-
Logger.EndGroup();
19+
var error = ValidateModels(context, storageSets);
20+
if (error == null)
21+
{
22+
var metadataMap = LoadMetadataList(context, storageSets, contextType);
23+
total = SaveStorageSets(context, total, contextType, storageSets, metadataMap);
24+
Logger.EndGroup();
25+
}
26+
else
27+
{
28+
BlazorLogger.Logger.Error("SaveChanges() terminated due to validation error");
29+
Logger.EndGroup();
30+
throw new BlazorDBUpdateException(error);
31+
}
32+
2133
return total;
2234
}
2335

36+
private string ValidateModels(StorageContext context, IEnumerable<PropertyInfo> storageSets)
37+
{
38+
string error = null;
39+
foreach (var storeageSetProp in storageSets)
40+
{
41+
var storeageSet = storeageSetProp.GetValue(context);
42+
var listProp = storeageSet.GetType().GetProperty(StorageManagerUtil.List, StorageManagerUtil.Flags);
43+
var list = listProp.GetValue(storeageSet);
44+
var method = list.GetType().GetMethod(StorageManagerUtil.GetEnumerator);
45+
var enumerator = (IEnumerator)method.Invoke(list, new object[] { });
46+
while (enumerator.MoveNext())
47+
{
48+
var model = enumerator.Current;
49+
foreach (var prop in model.GetType().GetProperties())
50+
{
51+
if (Attribute.IsDefined(prop, typeof(Required)))
52+
{
53+
var value = prop.GetValue(model);
54+
if (value == null)
55+
{
56+
error =
57+
$"{model.GetType().FullName}.{prop.Name} is a required field. SaveChanges() has been terminated.";
58+
break;
59+
}
60+
}
61+
62+
if (Attribute.IsDefined(prop, typeof(MaxLength)))
63+
{
64+
var maxLength = (MaxLength) Attribute.GetCustomAttribute(prop, typeof(MaxLength));
65+
var value = prop.GetValue(model);
66+
if (value != null)
67+
{
68+
var str = value.ToString();
69+
if (str.Length > maxLength.length)
70+
{
71+
error =
72+
$"{model.GetType().FullName}.{prop.Name} length is longer than {maxLength.length}. SaveChanges() has been terminated.";
73+
break;
74+
}
75+
}
76+
}
77+
}
78+
79+
if (error != null) break;
80+
}
81+
}
82+
83+
return error;
84+
}
85+
2486
private static IReadOnlyDictionary<string, Metadata> LoadMetadataList(StorageContext context,
2587
IEnumerable<PropertyInfo> storageSets, Type contextType)
2688
{

src/Sample/Models/Person.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
using System.Collections.Generic;
2+
using BlazorDB.DataAnnotations;
23

34
namespace Sample.Models
45
{
56
public class Person
67
{
78
public int Id { get; set; }
9+
[Required]
810
public string FirstName { get; set; }
11+
[MaxLength(20)]
912
public string LastName { get; set; }
1013
public Address HomeAddress { get; set; }
1114
public List<Address> OtherAddresses { get; set; }

src/Sample/Pages/Index.cshtml

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,11 @@
1212

1313
<button onclick="@OnclickSaveChanges">SaveChanges</button>
1414

15+
<h2>Validations</h2>
16+
17+
<button onclick="@OnRequired">Required</button>
18+
19+
<button onclick="@OnMaxLength">Max Length</button>
1520

1621
@if (@Person != null)
1722
{
@@ -54,4 +59,18 @@
5459
{
5560
Context.SaveChanges();
5661
}
62+
63+
void OnRequired()
64+
{
65+
var person = new Person {LastName = "Firstname required!"};
66+
Context.People.Add(person);
67+
Context.SaveChanges();
68+
}
69+
70+
void OnMaxLength()
71+
{
72+
var person = new Person { FirstName = "Lastname is long", LastName = "This is a very long last name and should throw!" };
73+
Context.People.Add(person);
74+
Context.SaveChanges();
75+
}
5776
}

0 commit comments

Comments
 (0)