Skip to content

Commit 9c87009

Browse files
committed
0.16.1 improvements from 0.16
1 parent c85fda6 commit 9c87009

10 files changed

+296
-49
lines changed

src/Entity/ValueItem.cs

+168
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
// The Sisk Framework source code
2+
// Copyright (c) 2023 PROJECT PRINCIPIUM
3+
//
4+
// The code below is licensed under the MIT license as
5+
// of the date of its publication, available at
6+
//
7+
// File name: ValueItem.cs
8+
// Repository: https://github.com/sisk-http/core
9+
10+
using Sisk.Core.Internal;
11+
using System;
12+
using System.Collections.Generic;
13+
using System.Linq;
14+
using System.Text;
15+
using System.Threading.Tasks;
16+
17+
namespace Sisk.Core.Entity;
18+
19+
public class ValueItem
20+
{
21+
private string? _ref;
22+
private string argName;
23+
private string argType;
24+
25+
internal ValueItem(string name, string type, string? data)
26+
{
27+
_ref = data;
28+
argName = name;
29+
argType = type;
30+
}
31+
32+
public string Name { get => argName; }
33+
public string? Value { get => _ref; }
34+
public bool IsNullOrEmpty { get => string.IsNullOrEmpty(_ref); }
35+
public bool IsNull { get => _ref == null; }
36+
37+
public ValueItem? MaybeNull()
38+
{
39+
if (IsNull)
40+
{
41+
return null;
42+
}
43+
return this;
44+
}
45+
46+
public string GetString()
47+
{
48+
ThrowIfNull();
49+
return _ref!;
50+
}
51+
52+
public int GetInteger()
53+
{
54+
ThrowIfNull();
55+
try
56+
{
57+
return int.Parse(_ref!);
58+
}
59+
catch (Exception ex) when (ex is FormatException || ex is InvalidCastException)
60+
{
61+
throw new FormatException(string.Format(SR.ValueItem_CastException, _ref, argName, "integer"));
62+
}
63+
}
64+
65+
public int GetByte()
66+
{
67+
ThrowIfNull();
68+
try
69+
{
70+
return byte.Parse(_ref!);
71+
}
72+
catch (Exception ex) when (ex is FormatException || ex is InvalidCastException)
73+
{
74+
throw new FormatException(string.Format(SR.ValueItem_CastException, _ref, argName, "byte"));
75+
}
76+
}
77+
78+
public long GetLong()
79+
{
80+
ThrowIfNull();
81+
try
82+
{
83+
return long.Parse(_ref!);
84+
}
85+
catch (Exception ex) when (ex is FormatException || ex is InvalidCastException)
86+
{
87+
throw new FormatException(string.Format(SR.ValueItem_CastException, _ref, argName, "long"));
88+
}
89+
}
90+
91+
public short GetShort()
92+
{
93+
ThrowIfNull();
94+
try
95+
{
96+
return short.Parse(_ref!);
97+
}
98+
catch (Exception ex) when (ex is FormatException || ex is InvalidCastException)
99+
{
100+
throw new FormatException(string.Format(SR.ValueItem_CastException, _ref, argName, "short"));
101+
}
102+
}
103+
104+
public double GetDouble()
105+
{
106+
ThrowIfNull();
107+
try
108+
{
109+
return double.Parse(_ref!);
110+
}
111+
catch (Exception ex) when (ex is FormatException || ex is InvalidCastException)
112+
{
113+
throw new FormatException(string.Format(SR.ValueItem_CastException, _ref, argName, "double"));
114+
}
115+
}
116+
117+
public bool GetBoolean()
118+
{
119+
ThrowIfNull();
120+
try
121+
{
122+
return bool.Parse(_ref!);
123+
}
124+
catch (Exception ex) when (ex is FormatException || ex is InvalidCastException)
125+
{
126+
throw new FormatException(string.Format(SR.ValueItem_CastException, _ref, argName, "boolean"));
127+
}
128+
}
129+
130+
public DateTime GetDateTime()
131+
{
132+
ThrowIfNull();
133+
try
134+
{
135+
return DateTime.Parse(_ref!);
136+
}
137+
catch (Exception ex) when (ex is FormatException || ex is InvalidCastException)
138+
{
139+
throw new FormatException(string.Format(SR.ValueItem_CastException, _ref, argName, "DateTime"));
140+
}
141+
}
142+
143+
public Guid GetGuid()
144+
{
145+
ThrowIfNull();
146+
try
147+
{
148+
return Guid.Parse(_ref!);
149+
}
150+
catch (Exception ex) when (ex is FormatException || ex is InvalidCastException)
151+
{
152+
throw new FormatException(string.Format(SR.ValueItem_CastException, _ref, argName, "GUID"));
153+
}
154+
}
155+
156+
void ThrowIfNull()
157+
{
158+
if (IsNull)
159+
{
160+
throw new NullReferenceException(string.Format(SR.ValueItem_ValueNull, argName, argType));
161+
}
162+
}
163+
164+
public static implicit operator string?(ValueItem i)
165+
{
166+
return i.Value;
167+
}
168+
}

src/Entity/ValueItemCollection.cs

+93
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
// The Sisk Framework source code
2+
// Copyright (c) 2023 PROJECT PRINCIPIUM
3+
//
4+
// The code below is licensed under the MIT license as
5+
// of the date of its publication, available at
6+
//
7+
// File name: KeyValueCollection.cs
8+
// Repository: https://github.com/sisk-http/core
9+
10+
using System;
11+
using System.Collections;
12+
using System.Collections.Generic;
13+
using System.Collections.Specialized;
14+
using System.Diagnostics.CodeAnalysis;
15+
using System.Linq;
16+
using System.Text;
17+
using System.Threading.Tasks;
18+
19+
namespace Sisk.Core.Entity;
20+
21+
public sealed class ValueItemCollection : IEnumerable<ValueItem>
22+
{
23+
internal Dictionary<string, string?> items;
24+
internal string paramName;
25+
26+
internal static ValueItemCollection FromNameValueCollection(string paramName, NameValueCollection col)
27+
{
28+
ValueItemCollection vcol = new ValueItemCollection(paramName);
29+
30+
foreach (string key in col.Keys)
31+
{
32+
vcol.items.Add(key, col[key]);
33+
}
34+
35+
return vcol;
36+
}
37+
38+
internal ValueItemCollection(string paramName)
39+
{
40+
items = new Dictionary<string, string?>(StringComparer.OrdinalIgnoreCase);
41+
this.paramName = paramName;
42+
}
43+
44+
internal void SetItem(string key, string? value)
45+
{
46+
items[key] = value;
47+
}
48+
49+
public Dictionary<string, string?> AsDictionary() => items;
50+
public NameValueCollection AsNameValueCollection()
51+
{
52+
NameValueCollection n = new NameValueCollection();
53+
54+
foreach (string key in items.Keys)
55+
{
56+
n.Add(key, items[key]);
57+
}
58+
59+
return n;
60+
}
61+
62+
public int Count { get => items.Count; }
63+
public ValueItem this[string name] { get => GetItem(name); }
64+
65+
public ValueItem GetItem(string name)
66+
{
67+
items.TryGetValue(name, out string? value);
68+
return new ValueItem(name, paramName, value);
69+
}
70+
71+
public IEnumerator<ValueItem> GetEnumerator()
72+
{
73+
foreach (string key in items.Keys)
74+
{
75+
yield return new ValueItem(key, paramName, items[key]);
76+
}
77+
}
78+
79+
IEnumerator IEnumerable.GetEnumerator()
80+
{
81+
return this.GetEnumerator();
82+
}
83+
84+
public static implicit operator Dictionary<string, string>(ValueItemCollection vcol)
85+
{
86+
return vcol.AsDictionary();
87+
}
88+
89+
public static implicit operator NameValueCollection(ValueItemCollection vcol)
90+
{
91+
return vcol.AsNameValueCollection();
92+
}
93+
}

src/Http/HttpRequest.cs

+23-7
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@ public sealed class HttpRequest
5555
private HttpRequestEventSource? activeEventSource;
5656
private NameValueCollection? headers = null;
5757
private NameValueCollection? cookies = null;
58+
private ValueItemCollection? query = null;
59+
private ValueItemCollection? form = null;
5860
private int currentFrame = 0;
5961

6062
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
@@ -69,7 +71,6 @@ internal HttpRequest(
6971
this.listenerResponse = context.Response;
7072
this.listenerRequest = context.Request;
7173
this.RequestedAt = DateTime.Now;
72-
this.Query = listenerRequest.QueryString;
7374
this.hostContext = host;
7475
}
7576

@@ -355,12 +356,22 @@ public long ContentLength
355356
/// Gets the HTTP request query extracted from the path string. This property also contains routing parameters.
356357
/// </summary>
357358
/// <definition>
358-
/// public NameValueCollection Query { get; }
359+
/// public ValueItemCollection Query { get; }
359360
/// </definition>
360361
/// <type>
361362
/// Property
362363
/// </type>
363-
public NameValueCollection Query { get; internal set; }
364+
public ValueItemCollection Query
365+
{
366+
get
367+
{
368+
if (query == null)
369+
{
370+
query = ValueItemCollection.FromNameValueCollection("query parameter", listenerRequest.QueryString);
371+
}
372+
return query;
373+
}
374+
}
364375

365376
/// <summary>
366377
/// Gets the HTTP request URL raw query string.
@@ -455,9 +466,13 @@ public MultipartFormCollection GetMultipartFormContent()
455466
/// <type>
456467
/// Method
457468
/// </type>
458-
public NameValueCollection GetFormContent()
469+
public ValueItemCollection GetFormContent()
459470
{
460-
return HttpUtility.ParseQueryString(Body);
471+
if (form == null)
472+
{
473+
form = ValueItemCollection.FromNameValueCollection("form", HttpUtility.ParseQueryString(Body));
474+
}
475+
return form;
461476
}
462477

463478
/// <summary>
@@ -556,7 +571,7 @@ public T GetContextBag<T>() where T : notnull
556571
/// <type>
557572
/// Method
558573
/// </type>
559-
public string? GetQueryValue(string queryKeyName) => Query[queryKeyName];
574+
public string? GetQueryValue(string queryKeyName) => Query[queryKeyName].MaybeNull()?.GetString();
560575

561576
/// <summary>
562577
/// Gets the value stored from the <see cref="Query"/> and converts it to the given type.
@@ -574,13 +589,14 @@ public T GetContextBag<T>() where T : notnull
574589
/// <type>
575590
/// Method
576591
/// </type>
592+
[Obsolete("This method is deprecated and will be removed in later versions. Use Query[queryKeyName] instead.")]
577593
#if NET6_0
578594
public T GetQueryValue<T>(string queryKeyName, T defaultValue = default) where T : struct
579595
#elif NET7_0_OR_GREATER
580596
public T GetQueryValue<T>(string queryKeyName, T defaultValue = default) where T : struct, IParsable<T>
581597
#endif
582598
{
583-
string? value = Query[queryKeyName];
599+
string? value = Query[queryKeyName].MaybeNull()?.GetString();
584600
if (value == null) return defaultValue;
585601

586602
try

src/Http/HttpResponse.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -301,12 +301,12 @@ public HttpResponse WithStatus(HttpStatusCode status)
301301
/// <param name="httpOnly">Determines if the cookie will be only available in the HTTP context.</param>
302302
/// <param name="sameSite">The cookie SameSite parameter.</param>
303303
/// <definition>
304-
/// public HttpResponse WithCookie(string name, string value, DateTime? expires, TimeSpan? maxAge, string? domain, string? path, bool? secure, bool? httpOnly, string? sameSite)
304+
/// public HttpResponse WithCookie(string name, string value, DateTime? expires = null, TimeSpan? maxAge = null, string? domain = null, string? path = null, bool? secure = null, bool? httpOnly = null, string? sameSite = null)
305305
/// </definition>
306306
/// <type>
307307
/// Method
308308
/// </type>
309-
public HttpResponse WithCookie(string name, string value, DateTime? expires, TimeSpan? maxAge, string? domain, string? path, bool? secure, bool? httpOnly, string? sameSite)
309+
public HttpResponse WithCookie(string name, string value, DateTime? expires = null, TimeSpan? maxAge = null, string? domain = null, string? path = null, bool? secure = null, bool? httpOnly = null, string? sameSite = null)
310310
{
311311
this.SetCookie(name, value, expires, maxAge, domain, path, secure, httpOnly, sameSite);
312312
return this;

src/Internal/SR.cs

+4
Original file line numberDiff line numberDiff line change
@@ -79,4 +79,8 @@ static class SR
7979
public const string InitializationParameterCollection_NullOrEmptyParameter = "The required parameter \"{0}\" is either empty or not present in the configuration file.";
8080
public const string InitializationParameterCollection_NullParameter = "The required parameter \"{0}\" is not present in the configuration file.";
8181
public const string InitializationParameterCollection_MapCastException = "Cannot cast the value \"{0}\" into an {1}.";
82+
83+
public const string ValueItem_ValueNull = "The value \"{0}\" contained at this {1} is null or it's undefined.";
84+
public const string ValueItem_CastException = "Cannot cast the value \"{0}\" at parameter {1} into an {2}.";
85+
8286
}

src/Routing/IRequestHandler.cs

-6
Original file line numberDiff line numberDiff line change
@@ -60,12 +60,6 @@ public interface IRequestHandler
6060
/// </type>
6161
public enum RequestHandlerExecutionMode
6262
{
63-
/// <summary>
64-
/// Indicates that the handler must be executed before the router calls the route action and before the request content is available.
65-
/// </summary>
66-
[Obsolete("This field is deprecated and will be removed in newer versions of Sisk. Use BeforeResponse instead.")]
67-
BeforeContents,
68-
6963
/// <summary>
7064
/// Indicates that the handler must be executed before the router calls the route action and after request contents is loaded.
7165
/// </summary>

src/Routing/RequestHandler.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ public abstract class RequestHandler : IRequestHandler
2424
{
2525
/// <inheritdoc/>
2626
/// <nodoc/>
27-
public virtual RequestHandlerExecutionMode ExecutionMode { get; init; } = RequestHandlerExecutionMode.BeforeContents;
27+
public virtual RequestHandlerExecutionMode ExecutionMode { get; init; } = RequestHandlerExecutionMode.BeforeResponse;
2828

2929
/// <inheritdoc/>
3030
/// <nodoc/>

0 commit comments

Comments
 (0)