@@ -32,7 +32,7 @@ public TwilioVoiceController(TwilioSetting settings, IServiceProvider services,
3232 /// <exception cref="ArgumentNullException"></exception>
3333 [ ValidateRequest ]
3434 [ HttpPost ( "twilio/voice/welcome" ) ]
35- public async Task < TwiMLResult > InitiateConversation ( VoiceRequest request , [ FromQuery ] string states , [ FromQuery ] string intent )
35+ public async Task < TwiMLResult > InitiateConversation ( VoiceRequest request , [ FromQuery ] string [ ] states , [ FromQuery ] string intent )
3636 {
3737 if ( request ? . CallSid == null )
3838 {
@@ -44,7 +44,7 @@ public async Task<TwiMLResult> InitiateConversation(VoiceRequest request, [FromQ
4444 VoiceResponse response ;
4545 if ( string . IsNullOrWhiteSpace ( intent ) )
4646 {
47- var url = $ "twilio/voice/{ conversationId } /receive/0?states= { states } ";
47+ var url = $ "twilio/voice/{ conversationId } /receive/0?{ GenerateStatesParameter ( states ) } ";
4848 response = twilio . ReturnNoninterruptedInstructions ( new List < string > { "twilio/welcome.mp3" } , url , true , timeout : 2 ) ;
4949 }
5050 else
@@ -62,14 +62,14 @@ public async Task<TwiMLResult> InitiateConversation(VoiceRequest request, [FromQ
6262 States = ParseStates ( states )
6363 } ;
6464 await messageQueue . EnqueueAsync ( callerMessage ) ;
65- response = new VoiceResponse ( ) . Redirect ( new Uri ( $ "{ _settings . CallbackHost } /twilio/voice/{ conversationId } /reply/{ seqNum } ?states= { states } ") , HttpMethod . Post ) ;
65+ response = new VoiceResponse ( ) . Redirect ( new Uri ( $ "{ _settings . CallbackHost } /twilio/voice/{ conversationId } /reply/{ seqNum } ?{ GenerateStatesParameter ( states ) } ") , HttpMethod . Post ) ;
6666 }
6767 return TwiML ( response ) ;
6868 }
6969
7070 [ ValidateRequest ]
7171 [ HttpPost ( "twilio/voice/{conversationId}/receive/{seqNum}" ) ]
72- public async Task < TwiMLResult > ReceiveCallerMessage ( [ FromRoute ] string conversationId , [ FromRoute ] int seqNum , [ FromQuery ] string states , VoiceRequest request , [ FromQuery ] int attempts = 1 )
72+ public async Task < TwiMLResult > ReceiveCallerMessage ( [ FromRoute ] string conversationId , [ FromRoute ] int seqNum , [ FromQuery ] string [ ] states , VoiceRequest request , [ FromQuery ] int attempts = 1 )
7373 {
7474 var twilio = _services . GetRequiredService < TwilioService > ( ) ;
7575 var messageQueue = _services . GetRequiredService < TwilioMessageQueue > ( ) ;
@@ -99,7 +99,7 @@ public async Task<TwiMLResult> ReceiveCallerMessage([FromRoute] string conversat
9999 } ;
100100 await messageQueue . EnqueueAsync ( callerMessage ) ;
101101
102- response = new VoiceResponse ( ) . Redirect ( new Uri ( $ "{ _settings . CallbackHost } /twilio/voice/{ conversationId } /reply/{ seqNum } ?states= { states } ") , HttpMethod . Post ) ;
102+ response = new VoiceResponse ( ) . Redirect ( new Uri ( $ "{ _settings . CallbackHost } /twilio/voice/{ conversationId } /reply/{ seqNum } ?{ GenerateStatesParameter ( states ) } ") , HttpMethod . Post ) ;
103103 }
104104 else
105105 {
@@ -117,11 +117,11 @@ public async Task<TwiMLResult> ReceiveCallerMessage([FromRoute] string conversat
117117 speechPaths . Add ( $ "twilio/say-it-again-{ Random . Shared . Next ( 1 , 5 ) } .mp3") ;
118118 speechPaths . Add ( $ "twilio/voice/speeches/{ conversationId } /{ lastRepy . SpeechFileName } ") ;
119119 }
120- response = twilio . ReturnInstructions ( speechPaths , $ "twilio/voice/{ conversationId } /receive/{ seqNum } ?states= { states } ", true ) ;
120+ response = twilio . ReturnInstructions ( speechPaths , $ "twilio/voice/{ conversationId } /receive/{ seqNum } ?{ GenerateStatesParameter ( states ) } ", true ) ;
121121 }
122122 else
123123 {
124- response = twilio . ReturnInstructions ( null , $ "twilio/voice/{ conversationId } /receive/{ seqNum } ?states= { states } &attempts={ ++ attempts } ", true ) ;
124+ response = twilio . ReturnInstructions ( null , $ "twilio/voice/{ conversationId } /receive/{ seqNum } ?{ GenerateStatesParameter ( states ) } &attempts={ ++ attempts } ", true ) ;
125125 }
126126 }
127127 return TwiML ( response ) ;
@@ -130,7 +130,7 @@ public async Task<TwiMLResult> ReceiveCallerMessage([FromRoute] string conversat
130130 [ ValidateRequest ]
131131 [ HttpPost ( "twilio/voice/{conversationId}/reply/{seqNum}" ) ]
132132 public async Task < TwiMLResult > ReplyCallerMessage ( [ FromRoute ] string conversationId , [ FromRoute ] int seqNum ,
133- [ FromQuery ] string states , VoiceRequest request )
133+ [ FromQuery ] string [ ] states , VoiceRequest request )
134134 {
135135 var nextSeqNum = seqNum + 1 ;
136136 var sessionManager = _services . GetRequiredService < ITwilioSessionManager > ( ) ;
@@ -185,7 +185,7 @@ public async Task<TwiMLResult> ReplyCallerMessage([FromRoute] string conversatio
185185 segIndex ++ ;
186186 }
187187 }
188- response = twilio . ReturnInstructions ( speechPaths , $ "twilio/voice/{ conversationId } /reply/{ seqNum } ?states= { states } ", true ) ;
188+ response = twilio . ReturnInstructions ( speechPaths , $ "twilio/voice/{ conversationId } /reply/{ seqNum } ?{ GenerateStatesParameter ( states ) } ", true ) ;
189189 await sessionManager . RemoveReplyIndicationAsync ( conversationId , seqNum ) ;
190190 }
191191 else
@@ -208,7 +208,7 @@ public async Task<TwiMLResult> ReplyCallerMessage([FromRoute] string conversatio
208208 instructions . Add ( $ "twilio/typing-{ typingIndex } .mp3") ;
209209 }
210210
211- response = twilio . ReturnInstructions ( instructions , $ "twilio/voice/{ conversationId } /reply/{ seqNum } ?states= { states } ", true ) ;
211+ response = twilio . ReturnInstructions ( instructions , $ "twilio/voice/{ conversationId } /reply/{ seqNum } ?{ GenerateStatesParameter ( states ) } ", true ) ;
212212 }
213213 }
214214 else
@@ -226,7 +226,7 @@ public async Task<TwiMLResult> ReplyCallerMessage([FromRoute] string conversatio
226226 response = twilio . ReturnInstructions ( new List < string >
227227 {
228228 $ "twilio/voice/speeches/{ conversationId } /{ reply . SpeechFileName } "
229- } , $ "twilio/voice/{ conversationId } /receive/{ nextSeqNum } ?states= { states } ", true , hints : reply . Hints ) ;
229+ } , $ "twilio/voice/{ conversationId } /receive/{ nextSeqNum } ?{ GenerateStatesParameter ( states ) } ", true , hints : reply . Hints ) ;
230230 }
231231 }
232232
@@ -246,22 +246,30 @@ public async Task<FileContentResult> GetSpeechFile([FromRoute] string conversati
246246 return result ;
247247 }
248248
249- private Dictionary < string , string > ParseStates ( string ? states )
249+ private Dictionary < string , string > ParseStates ( string [ ] states )
250250 {
251251 var result = new Dictionary < string , string > ( ) ;
252- if ( string . IsNullOrWhiteSpace ( states ) )
252+ if ( states is null || ! states . Any ( ) )
253253 {
254254 return result ;
255255 }
256- var kvps = states . Split ( ',' , StringSplitOptions . TrimEntries | StringSplitOptions . RemoveEmptyEntries ) ;
257- foreach ( var kvp in kvps )
256+ foreach ( var kvp in states )
258257 {
259- var parts = kvp . Split ( ':' ) ;
258+ var parts = kvp . Split ( ':' , StringSplitOptions . TrimEntries | StringSplitOptions . RemoveEmptyEntries ) ;
260259 if ( parts . Length == 2 )
261260 {
262261 result . Add ( parts [ 0 ] , parts [ 1 ] ) ;
263262 }
264263 }
265264 return result ;
266265 }
266+
267+ private string GenerateStatesParameter ( string [ ] states )
268+ {
269+ if ( states is null || states . Length == 0 )
270+ {
271+ return null ;
272+ }
273+ return string . Join ( "&" , states . Select ( x => $ "states={ x } ") ) ;
274+ }
267275}
0 commit comments