8000 Merge pull request #95 from twilio-labs/twimlresult-refactor · twilio-labs/twilio-aspnet@f0de423 · GitHub
[go: up one dir, main page]

Skip to content

Commit f0de423

Browse files
authored
Merge pull request #95 from twilio-labs/twimlresult-refactor
Add Formatting Options to TwiML methods and classes + refactor
2 parents 1693469 + 5892f81 commit f0de423

19 files changed

+358
-278
lines changed

src/Twilio.AspNet.Core.UnitTests/MinimalApiTwiMLResultTests.cs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
11
using System.IO;
22
using System.Threading.Tasks;
33
using Microsoft.AspNetCore.Http;
4-
using Twilio.AspNet.Core.MinimalApi;
54
using Twilio.TwiML;
65
using Xunit;
76

87
namespace Twilio.AspNet.Core.UnitTests;
98

10-
// ReSharper disable once InconsistentNaming
119
public class MinimalApiTwiMLResultTests
1210
{
1311
[Fact]
@@ -32,6 +30,6 @@ private static async Task ValidateTwimlResultWritesToResponseBody(TwiML.TwiML tw
3230
Assert.Equal(twiMlResponse.ToString(), responseBody);
3331
}
3432

35-
private static VoiceResponse GetVoiceResponse() => new VoiceResponse().Say("Hello World");
36-
private static MessagingResponse GetMessagingResponse() => new MessagingResponse().Message("Hello World");
33+
private static VoiceResponse GetVoiceResponse() => new VoiceResponse().Say("Ahoy!");
34+
private static MessagingResponse GetMessagingResponse() => new MessagingResponse().Message("Ahoy!");
3735
}

src/Twilio.AspNet.Core.UnitTests/RequestValidationHelperTests.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,11 @@ public class ContextMocks
1616
public Moq.Mock<HttpContext> HttpContext { get; set; }
1717
public Moq.Mock<HttpRequest> Request { get; set; }
1818

19-
public ContextMocks(bool isLocal, FormCollection? form = null, bool isProxied = false) : this("", isLocal, form, isProxied)
19+
public ContextMocks(bool isLocal, FormCollection < F438 span class="pl-s1">form = null, bool isProxied = false) : this("", isLocal, form, isProxied)
2020
{
2121
}
2222

23-
public ContextMocks(string urlOverride, bool isLocal, FormCollection? form = null, bool isProxied = false)
23+
public ContextMocks(string urlOverride, bool isLocal, FormCollection form = null, bool isProxied = false)
2424
{
2525
var headers = new HeaderDictionary();
2626
headers.Add("X-Twilio-Signature", CalculateSignature(urlOverride, form));
@@ -56,7 +56,7 @@ public ContextMocks(string urlOverride, bool isLocal, FormCollection? form = nul
5656
public static string fakeUrl = "https://api.example.com/webhook";
5757
public static string fakeAuthToken = "thisisafakeauthtoken";
5858

59-
private string CalculateSignature(string urlOverride, FormCollection? form)
59+
private string CalculateSignature(string urlOverride, FormCollection form)
6060
{
6161
var value = new StringBuilder();
6262
value.Append(string.IsNullOrEmpty(urlOverride) ? ContextMocks.fakeUrl : urlOverride);

src/Twilio.AspNet.Core.UnitTests/Twilio.AspNet.Core.UnitTests.csproj

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22
<PropertyGroup>
33
<TargetFramework>net6.0</TargetFramework>
4-
<Nullable>enable</Nullable>
54
<IsPackable>false</IsPackable>
65
</PropertyGroup>
76
<ItemGroup>

src/Twilio.AspNet.Core.UnitTests/TwilioClientTests.cs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -213,10 +213,10 @@ public void AddTwilioClient_With_ApiKeyOptions_Should_Match_Properties()
213213
Assert.Equal(ValidTwilioOptions.Client.AccountSid, client.AccountSid);
214214
Assert.Equal(ValidTwilioOptions.Client.LogLevel, client.LogLevel);
215215
Assert.Equal(ValidTwilioOptions.Client.ApiKeySid,
216-
typeof(TwilioRestClient).GetField("_username", BindingFlags.NonPublic | BindingFlags.Instance)
216+
typeof(TwilioRestClient).GetField("_username", BindingFlags.NonPublic | BindingFlags.Instance)!
217217
.GetValue(client));
218218
Assert.Equal(ValidTwilioOptions.Client.ApiKeySecret,
219-
typeof(TwilioRestClient).GetField("_password", BindingFlags.NonPublic | BindingFlags.Instance)
219+
typeof(TwilioRestClient).GetField("_password", BindingFlags.NonPublic | BindingFlags.Instance)!
220220
.GetValue(client));
221221
}
222222

@@ -236,10 +236,10 @@ public void AddTwilioClient_With_AuthTokenOptions_Should_Match_Properties()
236236
Assert.Equal(ValidTwilioOptions.Client.AccountSid, client.AccountSid);
237237
Assert.Equal(ValidTwilioOptions.Client.LogLevel, client.LogLevel);
238238
Assert.Equal(ValidTwilioOptions.Client.AccountSid,
239-
typeof(TwilioRestClient).GetField("_username", BindingFlags.NonPublic | BindingFlags.Instance)
239+
typeof(TwilioRestClient).GetField("_username", BindingFlags.NonPublic | BindingFlags.Instance)!
240240
.GetValue(client));
241241
Assert.Equal(ValidTwilioOptions.Client.AuthToken,
242-
typeof(TwilioRestClient).GetField("_password", BindingFlags.NonPublic | BindingFlags.Instance)
242+
typeof(TwilioRestClient).GetField("_password", BindingFlags.NonPublic | BindingFlags.Instance)!
243243
.GetValue(client));
244244
}
245245
[Fact]
@@ -257,7 +257,7 @@ public void AddTwilioClient_Without_HttpClientProvider_Should_Named_HttpClient()
257257
var twilioRestClient = scope.ServiceProvider.GetService<TwilioRestClient>();
258258

259259
var actualHttpClient = (System.Net.Http.HttpClient) typeof(SystemNetHttpClient)
260-
.GetField("_httpClient", BindingFlags.NonPublic | BindingFlags.Instance)
260+
.GetField("_httpClient", BindingFlags.NonPublic | BindingFlags.Instance)!
261261
.GetValue(twilioRestClient.HttpClient);
262262

263263
Assert.NotNull(actualHttpClient);
@@ -271,14 +271,15 @@ public void AddTwilioClient_With_HttpClientProvider_Should_Use_HttpClient()
271271
serviceCollection.AddSingleton(BuildValidConfiguration());
272272

273273
using var httpClient = new System.Net.Http.HttpClient();
274+
// ReSharper disable once AccessToDisposedClosure
274275
serviceCollection.AddTwilioClient(_ => httpClient);
275276

276277
var serviceProvider = serviceCollection.BuildServiceProvider();
277278
using var scope = serviceProvider.CreateScope();
278279

279280
var twilioRestClient = scope.ServiceProvider.GetService<TwilioRestClient>();
280281
var httpClientFromTwilioClient = (System.Net.Http.HttpClient) typeof(SystemNetHttpClient)
281-
.GetField("_httpClient", BindingFlags.NonPublic | BindingFlags.Instance)
282+
.GetField("_httpClient", BindingFlags.NonPublic | BindingFlags.Instance)!
282283
.GetValue(twilioRestClient.HttpClient);
283284

284285
Assert.Equal(httpClient, httpClientFromTwilioClient);

src/Twilio.AspNet.Core.UnitTests/TwilioControllerExtensionTests.cs

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System.IO;
22
using System.Threading.Tasks;
3+
using System.Xml.Linq;
34
using Microsoft.AspNetCore.Http;
45
using Microsoft.AspNetCore.Mvc;
56
using Microsoft.AspNetCore.Mvc.Abstractions;
@@ -17,7 +18,7 @@ public class TwilioControllerExtensionTests
1718
[Fact]
1819
public async Task TwimlResult_Should_Write_VoiceResponse_To_ResponseBody()
1920
{
20-
var twiml = new VoiceResponse().Say("Hello World");
21+
var twiml = new VoiceResponse().Say("Ahoy!");
2122
var result = TwilioControllerExtensions.TwiML(Mock.Of<ControllerBase>(), twiml);
2223
var actionContext = CreateActionContext();
2324
await result.ExecuteResultAsync(actionContext);
@@ -27,11 +28,25 @@ public async Task TwimlResult_Should_Write_VoiceResponse_To_ResponseBody()
2728
var responseBody = await reader.ReadToEndAsync();
2829
Assert.Equal(twiml.ToString(), responseBody);
2930
}
31+
32+
[Fact]
33+
public async Task TwimlResult_Should_Write_VoiceResponse_To_ResponseBody_Unformatted()
34+
{
35+
var twiml = new VoiceResponse().Say("Ahoy!");
36+
var result = TwilioControllerExtensions.TwiML(Mock.Of<ControllerBase>(), twiml, SaveOptions.DisableFormatting);
37+
var actionContext = CreateActionContext();
38+
await result.ExecuteResultAsync(actionContext);
39+
40+
actionContext.HttpContext.Response.Body.Seek(0, SeekOrigin.Begin);
41+
var reader = new StreamReader(actionContext.HttpContext.Response.Body);
42+
var responseBody = await reader.ReadToEndAsync();
43+
Assert.Equal(twiml.ToString(SaveOptions.DisableFormatting), responseBody);
44+
}
3045

3146
[Fact]
3247
public async Task TwimlResult_Should_Write_MessagingResponse_To_ResponseBody()
3348
{
34-
var twiml = new MessagingResponse().Message("Hello World");
49+
var twiml = new MessagingResponse().Message("Ahoy!");
3550
var result = TwilioControllerExtensions.TwiML(Mock.Of<ControllerBase>(), twiml);
3651
var actionContext = CreateActionContext();
3752
await result.ExecuteResultAsync(actionContext);

src/Twilio.AspNet.Core/MinimalApiTwiMLResult.cs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1+
using System.Text;
12
using System.Threading.Tasks;
23
using Microsoft.AspNetCore.Http;
34

4-
55
namespace Twilio.AspNet.Core;
66

77
/// <summary>
@@ -18,13 +18,12 @@ public static class ResultsExtensions
1818
// ReSharper disable once InconsistentNaming
1919
// ReSharper disable once UnusedParameter.Global
2020
public static TwiMLResult TwiML(this IResultExtensions results, TwiML.TwiML twimlResponse)
21-
=> new TwiMLResult(twimlResponse);
21+
=> new(twimlResponse);
2222
}
2323

2424
/// <summary>
2525
/// Writes TwiML object to the HTTP response body
2626
/// </summary>
27-
// ReSharper disable once InconsistentNaming
2827
public partial class TwiMLResult : IResult
2928
{
3029
/// <summary>
Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,23 @@
1-
using System;
2-
using System.Collections.Generic;
3-
using System.Text;
4-
using Twilio.TwiML;
1+
using Twilio.TwiML;
52

63
namespace Twilio.AspNet.Core
74
{
8-
// ReSharper disable once InconsistentNaming
95
public static class TwiMLExtensions
106
{
11-
// ReSharper disable once InconsistentNaming
12-
public static TwiMLResult ToTwiMLResult(this VoiceResponse voiceResponse)
13-
{
14-
return new TwiMLResult(voiceResponse);
15-
}
7+
/// <summary>
8+
/// Returns a properly formatted TwiML response
9+
/// </summary>
10+
/// <param name="voiceResponse"></param>
11+
/// <returns></returns>
12+
public static TwiMLResult ToTwiMLResult(this VoiceResponse voiceResponse)
13+
=> new TwiMLResult(voiceResponse);
1614

17-
// ReSharper disable once InconsistentNaming
15+
/// <summary>
16+
/// Returns a properly formatted TwiML response
17+
/// </summary>
18+
/// <param name="messagingResponse"></param>
19+
/// <returns></returns>
1820
public static TwiMLResult ToTwiMLResult(this MessagingResponse messagingResponse)
19-
{
20-
return new TwiMLResult(messagingResponse);
21-
}
21+
=>new TwiMLResult(messagingResponse);
2222
}
2323
}

src/Twilio.AspNet.Core/TwiMLResult.cs

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
using System.Threading.Tasks;
2+
using System.Xml.Linq;
23
using Microsoft.AspNetCore.Http;
3 D96B 4
using Microsoft.AspNetCore.Mvc;
45

56
namespace Twilio.AspNet.Core
67
{
7-
// ReSharper disable once InconsistentNaming
8+
/// <summary>
9+
/// TwiMLResult writes TwiML to the HTTP response body
10+
/// </summary>
811
public partial class TwiMLResult : IActionResult
912
{
1013
public string Data { get; protected set; }
@@ -18,23 +21,25 @@ public TwiMLResult(string twiml)
1821
Data = twiml;
1922
}
2023

21-
public TwiMLResult(TwiML.TwiML response)
24+
public TwiMLResult(TwiML.TwiML response) : this(response, SaveOptions.None)
25+
{
26+
}
27+
28+
public TwiMLResult(TwiML.TwiML response, SaveOptions formattingOptions)
2229
{
2330
if (response != null)
24-
Data = response.ToString();
31+
Data = response.ToString(formattingOptions);
2532
}
2633

2734
public async Task ExecuteResultAsync(ActionContext actionContext)
2835
{
2936
var response = actionContext.HttpContext.Response;
3037
await WriteTwiMLToResponse(response);
3138
}
32-
33-
// ReSharper disable once InconsistentNaming
39+
3440
private async Task WriteTwiMLToResponse(HttpResponse response)
3541
{
3642
response.ContentType = "application/xml";
37-
3843
if (Data == null)
3944
{
4045
Data = "<Response></Response>";
Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using Microsoft.AspNetCore.Mvc;
1< F438 /td>+
using System.Xml.Linq;
2+
using Microsoft.AspNetCore.Mvc;
23
using Twilio.TwiML;
34

45
namespace Twilio.AspNet.Core
@@ -14,22 +15,34 @@ public class TwilioController : ControllerBase
1415
/// <param name="response"></param>
1516
/// <returns></returns>
1617
[NonAction]
17-
// ReSharper disable once InconsistentNaming
18-
public TwiMLResult TwiML(MessagingResponse response)
19-
{
20-
return new TwiMLResult(response);
21-
}
18+
public TwiMLResult TwiML(MessagingResponse response) => new TwiMLResult(response);
19+
20+
/// <summary>
21+
/// Returns a properly formatted TwiML response
22+
/// </summary>
23+
/// <param name="response"></param>
24+
/// <param name="formattingOptions"></param>
25+
/// <returns></returns>
26+
[NonAction]
27+
public TwiMLResult TwiML(MessagingResponse response, SaveOptions formattingOptions)
28+
=> new TwiMLResult(response, formattingOptions);
29+
30+
/// <summary>
31+
/// Returns a properly formatted TwiML response
32+
/// </summary>
33+
/// <param name="response"></param>
34+
/// <returns></returns>
35+
[NonAction]
36+
public TwiMLResult TwiML(VoiceResponse response) => new TwiMLResult(response);
2237

2338
/// <summary>
2439
/// Returns a properly formatted TwiML response
2540
/// </summary>
2641
/// <param name="response"></param>
42+
/// <param name="formattingOptions"></param>
2743
/// <returns></returns>
2844
[NonAction]
29-
// ReSharper disable once InconsistentNaming
30-
public TwiMLResult TwiML(VoiceResponse response)
31-
{
32-
return new TwiMLResult(response);
33-
}
45+
public TwiMLResult TwiML(VoiceResponse response, SaveOptions formattingOptions)
46+
=> new TwiMLResult(response, formattingOptions);
3447
}
3548
}

src/Twilio.AspNet.Core/TwilioControllerExtensions.cs

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using Microsoft.AspNetCore.Mvc;
1+
using System.Xml.Linq;
2+
using Microsoft.AspNetCore.Mvc;
23
using Twilio.TwiML;
34

45
namespace Twilio.AspNet.Core
@@ -14,18 +15,36 @@ public static class TwilioControllerExtensions
1415
/// <param name="controller"></param>
1516
/// <param name="response"></param>
1617
/// <returns></returns>
17-
// ReSharper disable once InconsistentNaming
1818
public static TwiMLResult TwiML(this ControllerBase controller, MessagingResponse response)
1919
=> new TwiMLResult(response);
20+
21+
/// <summary>
22+
/// Returns a properly formatted TwiML response
23+
/// </summary>
24+
/// <param name="controller"></param>
25+
/// <param name="response"></param>
26+
/// <param name="formattingOptions"></param>
27+
/// <returns></returns>
28+
public static TwiMLResult TwiML(this ControllerBase controller, MessagingResponse response, SaveOptions formattingOptions)
29+
=> new TwiMLResult(response, formattingOptions);
2030

2131
/// <summary>
2232
/// Returns a properly formatted TwiML response
2333
/// </summary>
2434
/// <param name="controller"></param>
2535
/// <param name="response"></param>
2636
/// <returns></returns>
27-
// ReSharper disable once InconsistentNaming
2837
public static TwiMLResult TwiML(this ControllerBase controller, VoiceResponse response)
2938
=> new TwiMLResult(response);
39+
40+
/// <summary>
41+
/// Returns a properly formatted TwiML response
42+
/// </summary>
43+
/// <param name="controller"></param>
44+
/// <param name="response"></param>
45+
/// <param name="formattingOptions"></param>
46+
/// <returns></returns>
47+
public static TwiMLResult TwiML(this ControllerBase controller, VoiceResponse response, SaveOptions formattingOptions)
48+
=> new TwiMLResult(response, formattingOptions);
3049
}
3150
}

0 commit comments

Comments
 (0)
0