1+ // Copyright (c) Winton. All rights reserved.
2+ // Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.
3+
4+ using System ;
5+ using System . Threading . Tasks ;
6+ using Microsoft . AspNetCore . Mvc ;
7+
8+ namespace Winton . DomainModelling . AspNetCore
9+ {
10+ /// <summary>
11+ /// Extension methods for converting <see cref="Result{TData}"/> types into <see cref="IActionResult"/> types.
12+ /// </summary>
13+ public static class ResultExtensions
14+ {
15+ /// <summary>
16+ /// Converts a <see cref="Result{Unit}"/> to an <see cref="IActionResult"/>.
17+ /// </summary>
18+ /// <param name="result">
19+ /// The result that this extension method is invoked on.
20+ /// </param>
21+ /// <returns>
22+ /// If this result is a success then a <see cref="NoContentResult"/> is returned;
23+ /// otherwise it is converted to the appropriate 4xx response with Problem Details
24+ /// containing information about the error.
25+ /// </returns>
26+ public static IActionResult ToActionResult ( this Result < Unit > result )
27+ {
28+ return result . ToActionResult ( null as Func < Error , ProblemDetails > ) ;
29+ }
30+
31+ /// <summary>
32+ /// Converts a <see cref="Result{Unit}"/> to an <see cref="IActionResult"/>.
33+ /// </summary>
34+ /// <param name="result">
35+ /// The result that this extension method is invoked on.
36+ /// </param>
37+ /// <param name="onError">
38+ /// The function that is invoked if this <paramref name="result"/> is a <see cref="Failure{TData}"/>.
39+ /// It is responsible for mapping the <see cref="Error"/> to <see cref="ProblemDetails"/>.
40+ /// If this function returns <code>null</code> then the default error mapping conventions are used.
41+ /// This therefore provides a way to customize the error mapping from <see cref="Error"/> to <see cref="ProblemDetails"/>.
42+ /// </param>
43+ /// <returns>
44+ /// If this result is a success then a <see cref="NoContentResult"/> is returned;
45+ /// otherwise it is converted to an error response containing <see cref="ProblemDetails"/>
46+ /// in the response body.
47+ /// </returns>
48+ public static IActionResult ToActionResult (
49+ this Result < Unit > result ,
50+ Func < Error , ProblemDetails > onError )
51+ {
52+ return result . Match ( _ => new NoContentResult ( ) , error => error . ToActionResult ( onError ) ) ;
53+ }
54+
55+ /// <summary>
56+ /// Converts a <see cref="Task{Result}"/> of a <see cref="Result{Unit}"/> to an <see cref="IActionResult"/>.
57+ /// </summary>
58+ /// <param name="resultTask">
59+ /// The asynchronous result that this extension method is invoked on.
60+ /// </param>
61+ /// <returns>
62+ /// If this result is a success then a <see cref="NoContentResult"/> is returned;
63+ /// otherwise it is converted to the appropriate 4xx response containing <see cref="ProblemDetails"/>
64+ /// in the response body.
65+ /// </returns>
66+ public static async Task < IActionResult > ToActionResult ( this Task < Result < Unit > > resultTask )
67+ {
68+ return ( await resultTask ) . ToActionResult ( ) ;
69+ }
70+
71+ /// <summary>
72+ /// Converts a <see cref="Task{Result}"/> of a <see cref="Result{Unit}"/> to an <see cref="IActionResult"/>.
73+ /// </summary>
74+ /// <param name="resultTask">
75+ /// The asynchronous result that this extension method is invoked on.
76+ /// </param>
77+ /// <param name="onError">
78+ /// The function that is invoked if this <paramref name="resultTask"/> is a <see cref="Failure{TData}"/>.
79+ /// It is responsible for mapping the <see cref="Error"/> to <see cref="ProblemDetails"/>.
80+ /// If this function returns <code>null</code> then the default error mapping conventions are used.
81+ /// This therefore provides a way to customize the error mapping from <see cref="Error"/> to <see cref="ProblemDetails"/>.
82+ /// </param>
83+ /// <returns>
84+ /// If this result is a success then a <see cref="NoContentResult"/> is returned;
85+ /// otherwise it is converted to an error response containing <see cref="ProblemDetails"/>
86+ /// in the response body.
87+ /// </returns>
88+ public static async Task < IActionResult > ToActionResult (
89+ this Task < Result < Unit > > resultTask ,
90+ Func < Error , ProblemDetails > onError )
91+ {
92+ return ( await resultTask ) . ToActionResult ( onError ) ;
93+ }
94+
95+ /// <summary>
96+ /// Converts a <see cref="Result{TData}"/> to an <see cref="ActionResult{TData}"/>.
97+ /// </summary>
98+ /// <typeparam name="TData">
99+ /// The type of data encapsulated by the result.
100+ /// </typeparam>
101+ /// <param name="result">
102+ /// The result that this extension method is invoked on.
103+ /// </param>
104+ /// <returns>
105+ /// If this result is a success then an <see cref="ActionResult{TData}"/> is returned;
106+ /// otherwise it is converted to the appropriate 4xx response containing <see cref="ProblemDetails"/>
107+ /// in the response body.
108+ /// </returns>
109+ public static ActionResult < TData > ToActionResult < TData > ( this Result < TData > result )
110+ {
111+ return result . ToActionResult ( null as Func < Error , ProblemDetails > ) ;
112+ }
113+
114+ /// <summary>
115+ /// Converts a <see cref="Result{TData}"/> to an <see cref="ActionResult{TData}"/>.
116+ /// </summary>
117+ /// <typeparam name="TData">
118+ /// The type of data encapsulated by the result.
119+ /// </typeparam>
120+ /// <param name="result">
121+ /// The result that this extension method is invoked on.
122+ /// </param>
123+ /// <param name="onError">
124+ /// The function that is invoked if this <paramref name="result"/> is a <see cref="Failure{TData}"/>.
125+ /// It is responsible for mapping the <see cref="Error"/> to <see cref="ProblemDetails"/>.
126+ /// If this function returns <code>null</code> then the default error mapping conventions are used.
127+ /// This therefore provides a way to customize the error mapping from <see cref="Error"/> to <see cref="ProblemDetails"/>.
128+ /// </param>
129+ /// <returns>
130+ /// If this result is a success then an <see cref="ActionResult{TData}"/> is returned;
131+ /// otherwise it is converted to an error response containing <see cref="ProblemDetails"/>
132+ /// in the response body.
133+ /// </returns>
134+ public static ActionResult < TData > ToActionResult < TData > (
135+ this Result < TData > result ,
136+ Func < Error , ProblemDetails > onError )
137+ {
138+ return result . Match ( data => new ActionResult < TData > ( data ) , error => error . ToActionResult ( onError ) ) ;
139+ }
140+
141+ /// <summary>
142+ /// Asynchronously converts a <see cref="Task{Result}"/> of a <see cref="Result{TData}"/>
143+ /// to an <see cref="ActionResult{TData}"/>.
144+ /// </summary>
145+ /// <typeparam name="TData">
146+ /// The type of data encapsulated by the result.
147+ /// </typeparam>
148+ /// <param name="resultTask">
149+ /// The asynchronous result that this extension method is invoked on.
150+ /// </param>
151+ /// <returns>
152+ /// If this result is a success then an <see cref="ActionResult{TData}"/> is returned;
153+ /// otherwise it is converted to the appropriate 4xx response containing <see cref="ProblemDetails"/>
154+ /// in the response body.
155+ /// </returns>
156+ public static async Task < ActionResult < TData > > ToActionResult < TData > ( this Task < Result < TData > > resultTask )
157+ {
158+ return ( await resultTask ) . ToActionResult ( ) ;
159+ }
160+
161+ /// <summary>
162+ /// Asynchronously converts a <see cref="Task{Result}"/> of a <see cref="Result{TData}"/>
163+ /// to an <see cref="ActionResult{TData}"/>.
164+ /// </summary>
165+ /// <typeparam name="TData">
166+ /// The type of data encapsulated by the result.
167+ /// </typeparam>
168+ /// <param name="resultTask">
169+ /// The asynchronous result that this extension method is invoked on.
170+ /// </param>
171+ /// <param name="onError">
172+ /// The function that is invoked if this <paramref name="resultTask"/> is a <see cref="Failure{TData}"/>.
173+ /// It is responsible for mapping the <see cref="Error"/> to <see cref="ProblemDetails"/>.
174+ /// If this function returns <code>null</code> then the default error mapping conventions are used.
175+ /// This therefore provides a way to customize the error mapping from <see cref="Error"/> to <see cref="ProblemDetails"/>.
176+ /// </param>
177+ /// <returns>
178+ /// If this result is a success then an <see cref="ActionResult{TData}"/> is returned;
179+ /// otherwise it is converted to an error response containing <see cref="ProblemDetails"/>
180+ /// in the response body.
181+ /// </returns>
182+ public static async Task < ActionResult < TData > > ToActionResult < TData > (
183+ this Task < Result < TData > > resultTask ,
184+ Func < Error , ProblemDetails > onError )
185+ {
186+ return ( await resultTask ) . ToActionResult ( onError ) ;
187+ }
188+
189+ /// <summary>
190+ /// Converts a <see cref="Result{TData}"/> to an <see cref="IActionResult"/>.
191+ /// </summary>
192+ /// <typeparam name="TData">
193+ /// The type of data encapsulated by the result.
194+ /// </typeparam>
195+ /// <param name="result">
196+ /// The result that this extension method is invoked on.
197+ /// </param>
198+ /// <param name="onSuccess">
199+ /// The function that is invoked if this <paramref name="result"/> is a <see cref="Success{TData}"/>.
200+ /// It is invoked to map the data to an <see cref="IActionResult"/>.
201+ /// </param>
202+ /// <returns>
203+ /// If this result is a success the result of <paramref name="onSuccess"/> is returned;
204+ /// otherwise it is converted to the appropriate 4xx response containing <see cref="ProblemDetails"/>
205+ /// in the response body.
206+ /// </returns>
207+ public static IActionResult ToActionResult < TData > (
208+ this Result < TData > result ,
209+ Func < TData , IActionResult > onSuccess )
210+ {
211+ return result . ToActionResult ( onSuccess , null ) ;
212+ }
213+
214+ /// <summary>
215+ /// Converts a <see cref="Result{TData}"/> to an <see cref="IActionResult"/>.
216+ /// </summary>
217+ /// <typeparam name="TData">
218+ /// The type of data encapsulated by the result.
219+ /// </typeparam>
220+ /// <param name="result">
221+ /// The result that this extension method is invoked on.
222+ /// </param>
223+ /// <param name="onSuccess">
224+ /// The function that is invoked if this <paramref name="result"/> is a <see cref="Success{TData}"/>.
225+ /// It is invoked to map the data to an <see cref="IActionResult"/>.
226+ /// </param>
227+ /// <param name="onError">
228+ /// The function that is invoked if this <paramref name="result"/> is a <see cref="Failure{TData}"/>.
229+ /// It is invoked to map the <see cref="Error"/> to <see cref="ProblemDetails"/>.
230+ /// If this function returns <code>null</code> then the default error mapping conventions are used.
231+ /// This therefore provides a way to customize the error mapping from <see cref="Error"/> to <see cref="ProblemDetails"/>.
232+ /// </param>
233+ /// <returns>
234+ /// If this result is a success the result of <paramref name="onSuccess"/> is returned;
235+ /// otherwise it is converted to an error response containing <see cref="ProblemDetails"/>
236+ /// in the response body.
237+ /// </returns>
238+ public static IActionResult ToActionResult < TData > (
239+ this Result < TData > result ,
240+ Func < TData , IActionResult > onSuccess ,
241+ Func < Error , ProblemDetails > onError )
242+ {
243+ return result . Match ( onSuccess , error => error . ToActionResult ( onError ) ) ;
244+ }
245+
246+ /// <summary>
247+ /// Asynchronously converts a <see cref="Task{Result}"/> of a <see cref="Result{TData}"/>
248+ /// to an <see cref="IActionResult"/>.
249+ /// </summary>
250+ /// <typeparam name="TData">
251+ /// The type of data encapsulated by the result.
252+ /// </typeparam>
253+ /// <param name="resultTask">
254+ /// The asynchronous result that this extension method is invoked on.
255+ /// </param>
256+ /// <param name="onSuccess">
257+ /// The function that is invoked if this <paramref name="resultTask"/> is a <see cref="Success{TData}"/>.
258+ /// It is invoked to map the data to an <see cref="IActionResult"/>.
259+ /// </param>
260+ /// <returns>
261+ /// If this result is a success the result of <paramref name="onSuccess"/> is returned;
262+ /// otherwise it is converted to the appropriate 4xx response containing <see cref="ProblemDetails"/>
263+ /// in the response body.
264+ /// </returns>
265+ public static async Task < IActionResult > ToActionResult < TData > (
266+ this Task < Result < TData > > resultTask ,
267+ Func < TData , IActionResult > onSuccess )
268+ {
269+ return ( await resultTask ) . ToActionResult ( onSuccess ) ;
270+ }
271+
272+ /// <summary>
273+ /// Asynchronously converts a <see cref="Task{Result}"/> of a <see cref="Result{TData}"/>
274+ /// to an <see cref="IActionResult"/>.
275+ /// </summary>
276+ /// <typeparam name="TData">
277+ /// The type of data encapsulated by the result.
278+ /// </typeparam>
279+ /// <param name="resultTask">
280+ /// The asynchronous result that this extension method is invoked on.
281+ /// </param>
282+ /// <param name="onSuccess">
283+ /// The function that is invoked if this <paramref name="resultTask"/> is a <see cref="Success{TData}"/>.
284+ /// It is invoked to map the data to an <see cref="IActionResult"/>.
285+ /// </param>
286+ /// <param name="onError">
287+ /// The function that is invoked if this <paramref name="resultTask"/> is a <see cref="Failure{TData}"/>.
288+ /// It is invoked to map the <see cref="Error"/> to <see cref="ProblemDetails"/>.
289+ /// If this function returns <code>null</code> then the default error mapping conventions are used.
290+ /// This therefore provides a way to customize the error mapping from <see cref="Error"/> to <see cref="ProblemDetails"/>.
291+ /// </param>
292+ /// <returns>
293+ /// If this result is a success the result of <paramref name="onSuccess"/> is returned;
294+ /// otherwise it is converted to an error response containing <see cref="ProblemDetails"/>
295+ /// in the response body.
296+ /// </returns>
297+ public static async Task < IActionResult > ToActionResult < TData > (
298+ this Task < Result < TData > > resultTask ,
299+ Func < TData , IActionResult > onSuccess ,
300+ Func < Error , ProblemDetails > onError )
301+ {
302+ return ( await resultTask ) . ToActionResult ( onSuccess , onError ) ;
303+ }
304+ }
305+ }
0 commit comments