Skip to content

Commit 1c67513

Browse files
committed
Updates to the AspNetCore Service Architecture
1 parent b852c02 commit 1c67513

39 files changed

+2515
-138
lines changed
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
2+
using System;
3+
using System.Collections.Generic;
4+
using System.Linq;
5+
using System.Text;
6+
namespace Demo.LicenseTrack.App.Model
7+
{
8+
/// <summary>
9+
/// Application data model that supports 'TblCustomer'
10+
/// </summary>
11+
public class CustomerAppModel
12+
{
13+
14+
public int Id {get; set; }
15+
public string FirstName {get; set; }
16+
public string LastName {get; set; }
17+
public string MiddleName {get; set; }
18+
public string Email {get; set; }
19+
public string Address {get; set; }
20+
public string Address2 {get; set; }
21+
public string City {get; set; }
22+
public string State {get; set; }
23+
public string PostalCode {get; set; }
24+
25+
26+
27+
28+
29+
30+
31+
32+
33+
34+
}
35+
}
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
2+
using System;
3+
using System.Collections.Generic;
4+
using System.Text;
5+
using FluentValidation;
6+
7+
namespace Demo.LicenseTrack.App.Model
8+
{
9+
/// <summary>
10+
/// Validation class that supports the model <see cref="CustomerAppModel"/>
11+
/// </summary>
12+
public class CustomerAppModelValidator:AbstractValidator<CustomerAppModel>
13+
{
14+
/// <summary>
15+
/// Creates a new instance of the validator.
16+
/// </summary>
17+
public CustomerAppModelValidator()
18+
{
19+
DataValidation();
20+
CustomValidation();
21+
}
22+
23+
/// <summary>
24+
/// Implementation of custom validation.
25+
/// </summary>
26+
private void CustomValidation()
27+
{
28+
//TODO: Add custom validation for 'CustomerAppModel'
29+
}
30+
31+
32+
/// <summary>
33+
/// Implementation of data annotation validation.
34+
/// </summary>
35+
private void DataValidation()
36+
{
37+
//Rules for the FirstName property.
38+
RuleFor(m => m.FirstName).MaximumLength(100).When(m => !string.IsNullOrEmpty(m.FirstName));
39+
40+
//Rules for the LastName property.
41+
RuleFor(m => m.LastName).MaximumLength(100).When(m => !string.IsNullOrEmpty(m.LastName));
42+
43+
//Rules for the MiddleName property.
44+
RuleFor(m => m.MiddleName).MaximumLength(100).When(m => !string.IsNullOrEmpty(m.MiddleName));
45+
46+
//Rules for the Email property.
47+
RuleFor(m => m.Email).MaximumLength(100).When(m => !string.IsNullOrEmpty(m.Email));
48+
49+
//Rules for the Address property.
50+
RuleFor(m => m.Address).MaximumLength(512).When(m => !string.IsNullOrEmpty(m.Address));
51+
52+
//Rules for the Address2 property.
53+
RuleFor(m => m.Address2).MaximumLength(512).When(m => !string.IsNullOrEmpty(m.Address2));
54+
55+
//Rules for the City property.
56+
RuleFor(m => m.City).MaximumLength(255).When(m => !string.IsNullOrEmpty(m.City));
57+
58+
//Rules for the State property.
59+
RuleFor(m => m.State).MaximumLength(10).When(m => !string.IsNullOrEmpty(m.State));
60+
61+
//Rules for the PostalCode property.
62+
RuleFor(m => m.PostalCode).MaximumLength(20).When(m => !string.IsNullOrEmpty(m.PostalCode));
63+
64+
65+
}
66+
67+
}
68+
}

Demos/LicenseTrack/AppCode/Demo.LicenseTrack.App.Model/LibraryLoader.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,14 +36,16 @@ protected override void LoadManualRegistration(IServiceCollection serviceCollect
3636

3737

3838

39+
3940
/// <summary>
4041
/// Automated registration of classes using transient registration.
4142
/// </summary>
4243
/// <param name="serviceCollection">The service collection to register services.</param>
4344
/// <param name="configuration">The configuration data used with register of services.</param>
4445
protected override void LoadRegistration(IServiceCollection serviceCollection, IConfiguration configuration)
4546
{
46-
//Intentionally blank
47+
//This method was auto generated, do not modify by hand!
48+
serviceCollection.AddTransient<FluentValidation.IValidator<CustomerAppModel>, CustomerAppModelValidator>();
4749
}
4850

4951

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
2+
using System;
3+
using System.Collections.Generic;
4+
using System.Text;
5+
using System.Threading.Tasks;
6+
using Demo.LicenseTrack.App.Model;
7+
namespace Demo.LicenseTrack.Client.Contracts
8+
{
9+
/// <summary>
10+
/// Abstract implementation that supports 'CustomerClient'/>
11+
/// </summary>
12+
public interface ICustomerClient
13+
{
14+
15+
16+
/// <summary>
17+
/// Adds a new instance of the <see cref="CustomerAppModel"/> model.
18+
/// </summary>
19+
Task<CustomerAppModel> AddAsync(CustomerAppModel customerAppModel);
20+
21+
/// <summary>
22+
/// Updates a instance of the <see cref="CustomerAppModel"/> model.
23+
/// </summary>
24+
Task<CustomerAppModel> UpdateAsync(CustomerAppModel customerAppModel);
25+
26+
/// <summary>
27+
/// Deletes the instance of the <see cref="CustomerAppModel"/> model.
28+
/// </summary>
29+
Task DeleteAsync(CustomerAppModel customerAppModel);
30+
31+
32+
}
33+
}
Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
2+
using System;
3+
using System.Collections.Generic;
4+
using System.Linq;
5+
using System.Text;
6+
using System.Threading.Tasks;
7+
using Microsoft.Extensions.Logging;
8+
using System.Net.Http;
9+
using System.Net.Http.Json;
10+
using CodeFactory.NDF;
11+
using Demo.LicenseTrack.Client.Contracts;
12+
using Demo.LicenseTrack.Client.Transport.Rest;
13+
using Demo.LicenseTrack.Transport.Rest.Model;
14+
namespace Demo.LicenseTrack.Client.Transport.Rest
15+
{
16+
/// <summary>
17+
/// Web abstraction implementation for abstraction contract 'ICustomerClient'
18+
/// </summary>
19+
public class CustomerClient:RestAbstraction, ICustomerClient
20+
{
21+
/// <summary>
22+
/// Url for the service being accessed by this abstraction.
23+
/// </summary>
24+
private readonly ServiceUrl _serviceUrl;
25+
26+
/// <summary>
27+
/// Creates a instance of the web abstraction.
28+
/// <param name="logger">Logger that supports this abstraction.</param>
29+
/// <param name="url">service url</param>
30+
/// </summary>
31+
public CustomerClient(ILogger<CustomerClient> logger, RestDemoLicenseTrackTransportRestServiceUrl url):base(logger)
32+
{
33+
_serviceUrl = url;
34+
}
35+
36+
/// <summary>
37+
/// Deletes the instance of the <see cref="CustomerAppModel"/> model.
38+
/// </summary>
39+
public async Task DeleteAsync(Demo.LicenseTrack.App.Model.CustomerAppModel customerAppModel)
40+
{
41+
_logger.InformationEnterLog();
42+
if(customerAppModel == null)
43+
{
44+
_logger.ErrorLog($"The parameter {nameof(customerAppModel)} was not provided. Will raise an argument exception");
45+
_logger.InformationExitLog();
46+
throw new ValidationException(nameof(customerAppModel));
47+
}
48+
49+
try
50+
{
51+
using (HttpClient httpClient = await GetHttpClient())
52+
{
53+
var serviceData = await httpClient.PostAsJsonAsync<Demo.LicenseTrack.App.Model.CustomerAppModel>($"{_serviceUrl.Url}/api/Customer/Delete", customerAppModel);
54+
55+
await RaiseUnhandledExceptionsAsync(serviceData);
56+
57+
var serviceResult = await serviceData.Content.ReadFromJsonAsync<NoDataResult>();
58+
59+
if (serviceResult == null) throw new ManagedException("Internal error occurred no data was returned");
60+
61+
serviceResult.RaiseException();
62+
63+
}
64+
}
65+
catch (ManagedException)
66+
{
67+
//Throwing the managed exception. Override this logic if you have logic in this method to handle managed errors.
68+
throw;
69+
}
70+
catch (Exception unhandledException)
71+
{
72+
_logger.ErrorLog("An unhandled exception occurred, see the exception for details. Will throw a UnhandledException", unhandledException);
73+
_logger.InformationExitLog();
74+
throw new UnhandledException();
75+
}
76+
77+
_logger.InformationExitLog();
78+
79+
}
80+
81+
82+
/// <summary>
83+
/// Updates a instance of the <see cref="CustomerAppModel"/> model.
84+
/// </summary>
85+
public async Task<Demo.LicenseTrack.App.Model.CustomerAppModel> UpdateAsync(Demo.LicenseTrack.App.Model.CustomerAppModel customerAppModel)
86+
{
87+
_logger.InformationEnterLog();
88+
if(customerAppModel == null)
89+
{
90+
_logger.ErrorLog($"The parameter {nameof(customerAppModel)} was not provided. Will raise an argument exception");
91+
_logger.InformationExitLog();
92+
throw new ValidationException(nameof(customerAppModel));
93+
}
94+
95+
Demo.LicenseTrack.App.Model.CustomerAppModel result = null;
96+
97+
try
98+
{
99+
using (HttpClient httpClient = await GetHttpClient())
100+
{
101+
var serviceData = await httpClient.PostAsJsonAsync<Demo.LicenseTrack.App.Model.CustomerAppModel>($"{_serviceUrl.Url}/api/Customer/Update", customerAppModel);
102+
103+
await RaiseUnhandledExceptionsAsync(serviceData);
104+
105+
var serviceResult = await serviceData.Content.ReadFromJsonAsync<ServiceResult<Demo.LicenseTrack.App.Model.CustomerAppModel>>();
106+
107+
if (serviceResult == null) throw new ManagedException("Internal error occurred no data was returned");
108+
109+
serviceResult.RaiseException();
110+
111+
result = serviceResult.Result;
112+
113+
}
114+
}
115+
catch (ManagedException)
116+
{
117+
//Throwing the managed exception. Override this logic if you have logic in this method to handle managed errors.
118+
throw;
119+
}
120+
catch (Exception unhandledException)
121+
{
122+
_logger.ErrorLog("An unhandled exception occurred, see the exception for details. Will throw a UnhandledException", unhandledException);
123+
_logger.InformationExitLog();
124+
throw new UnhandledException();
125+
}
126+
127+
_logger.InformationExitLog();
128+
129+
return result;
130+
}
131+
132+
133+
/// <summary>
134+
/// Adds a new instance of the <see cref="CustomerAppModel"/> model.
135+
/// </summary>
136+
public async Task<Demo.LicenseTrack.App.Model.CustomerAppModel> AddAsync(Demo.LicenseTrack.App.Model.CustomerAppModel customerAppModel)
137+
{
138+
_logger.InformationEnterLog();
139+
if(customerAppModel == null)
140+
{
141+
_logger.ErrorLog($"The parameter {nameof(customerAppModel)} was not provided. Will raise an argument exception");
142+
_logger.InformationExitLog();
143+
throw new ValidationException(nameof(customerAppModel));
144+
}
145+
146+
Demo.LicenseTrack.App.Model.CustomerAppModel result = null;
147+
148+
try
149+
{
150+
using (HttpClient httpClient = await GetHttpClient())
151+
{
152+
var serviceData = await httpClient.PostAsJsonAsync<Demo.LicenseTrack.App.Model.CustomerAppModel>($"{_serviceUrl.Url}/api/Customer/Add", customerAppModel);
153+
154+
await RaiseUnhandledExceptionsAsync(serviceData);
155+
156+
var serviceResult = await serviceData.Content.ReadFromJsonAsync<ServiceResult<Demo.LicenseTrack.App.Model.CustomerAppModel>>();
157+
158+
if (serviceResult == null) throw new ManagedException("Internal error occurred no data was returned");
159+
160+
serviceResult.RaiseException();
161+
162+
result = serviceResult.Result;
163+
164+
}
165+
}
166+
catch (ManagedException)
167+
{
168+
//Throwing the managed exception. Override this logic if you have logic in this method to handle managed errors.
169+
throw;
170+
}
171+
catch (Exception unhandledException)
172+
{
173+
_logger.ErrorLog("An unhandled exception occurred, see the exception for details. Will throw a UnhandledException", unhandledException);
174+
_logger.InformationExitLog();
175+
throw new UnhandledException();
176+
}
177+
178+
_logger.InformationExitLog();
179+
180+
return result;
181+
}
182+
183+
184+
}
185+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
2+
using System;
3+
using System.Collections.Generic;
4+
using System.Linq;
5+
using System.Text;
6+
7+
namespace Demo.LicenseTrack.Client.Transport.Rest
8+
{
9+
/// <summary>
10+
/// Extensions for string type management with json data.
11+
/// </summary>
12+
public static class JsonServiceExtensions
13+
{
14+
/// <summary>
15+
/// Place holder value used when passing strings in rest.
16+
/// </summary>
17+
private static string RestPostPlaceHolderValueForString = "~~~Empty~~~";
18+
19+
/// <summary>
20+
/// Extension method that sets the post value for a string. If the string is null or empty will send a formatted string to represent empty or null.
21+
/// </summary>
22+
/// <param name="source">Source string to set.</param>
23+
/// <returns>The formatted string value.</returns>
24+
public static string SetPostValue(this string source)
25+
{
26+
return string.IsNullOrEmpty(source) ? RestPostPlaceHolderValueForString : source;
27+
}
28+
29+
/// <summary>
30+
/// Extension method that gets the received value from a post. Will check for the empty value to convert the result to null or will pass the returned response.
31+
/// </summary>
32+
/// <param name="source">Source string to get.</param>
33+
/// <returns>The formatted string value or null.</returns>
34+
public static string GetPostValue(this string source)
35+
{
36+
return source != RestPostPlaceHolderValueForString ? source : null;
37+
}
38+
39+
/// <summary>
40+
/// Extension method that determines if the string has a value or is empty.
41+
/// </summary>
42+
/// <param name="source">Source string to check for a value.</param>
43+
/// <returns>True has a value or false if not.</returns>
44+
public static bool HasValue(this string source)
45+
{
46+
return !string.IsNullOrEmpty(source);
47+
}
48+
49+
}
50+
}

0 commit comments

Comments
 (0)