Port Out Validation Implementation Example in C#

This document is a walkthrough of implementing a sample solution for using Bandwidth’s Port Out Validation.
Please see the first post in this series for a guide on how port out validation works.
This is a sample ValuesController.cs file using namespace Microsoft.AspNetCore.Mvc to create a route that can receive a webhook from Bandwidth. This sample code assumes at least some familiarity with C#, .NET Core, and ASP.NET Core. This is not meant to be a fully implemented port out validation solution, but rather a brief example of the general process of how a successful port out validation solution works. Please consult with your own teams about your company’s needs for this kind of solution, and remember that Bandwidth is always here to answer questions and provide guidance.
THE CODE:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml;
using Microsoft.AspNetCore.Mvc;
namespace pov.Controllers
{
//define our stored values we are validating against
public class validValues
{
public static string[] numbersStored = new string[2] { "9992228888", "3334442222" };
public static string accountIdStored = "1234";
public static string pinStored = "567";
}
[Route("api/pov")]
[Produces("application/xml")]
[ApiController]
public class ValuesController : ControllerBase
{
//defining our functions that validate against our stored data
private bool CheckNumber(string number)
{
return validValues.numbersStored.Contains(number);
}
private bool CheckAccountId(string accountId)
{
return validValues.accountIdStored == accountId;
}
private bool CheckPin(string pin)
{
return validValues.pinStored == pin;
}
//generates validation failure XML
private XmlDocument ValidationFails(List<string> errorTypes, string PON)
{
XmlDocument failXml = new XmlDocument();
string xmlBeginning = "<PortOutValidationResponse>" +
"<Portable>false</Portable>" +
"<PON>" + PON + "</PON>" +
"<Errors>";
string xmlEnd = "</Errors>" +
"<AcceptableValues>" +
"<Pin>" + validValues.pinStored + "</Pin>" +
"<AccountNumber>" + validValues.accountIdStored + "</AccountNumber>" +
"<TelephoneNumbers>" +
"<TelephoneNumber>" + validValues.numbersStored[0] + "</TelephoneNumber>" +
"<TelephoneNumber>" + validValues.numbersStored[1] + "</TelephoneNumber>" +
"</TelephoneNumbers>" +
"</AcceptableValues>" +
"</PortOutValidationResponse>";
//loops through types of errors to add them to XML
for (int i = 0; i < errorTypes.Count; i++)
{
switch (errorTypes[i])
{
case ("bad_number"):
errorTypes[i] = "<Error>" +
"<Code>7518</Code>" +
"<Description>Telephone Number Not Active</Description>" +
"</Error>";
break;
case ("bad_account"):
errorTypes[i] = "<Error>" +
"<Code>7511</Code>" +
"<Description>Invalid Account Code</Description>" +
"</Error>";
break;
case ("bad_pin"):
errorTypes[i] = "<Error>" +
"<Code>7513</Code>" +
"<Description>PIN Invalid</Description>" +
"</Error>";
break;
case ("no_account"):
errorTypes[i] = "<Error>" +
"<Code>7510</Code>" +
"<Description>Required account Code missing</Description>" +
"</Error>";
break;
case ("no_pin"):
errorTypes[i] = "<Error>" +
"<Code>7512</Code>" +
"<Description>Required PIN missing</Description>" +
"</Error>";
break;
}
}
string errorXmlString = string.Join("", errorTypes);
failXml.LoadXml(xmlBeginning + errorXmlString + xmlEnd);
return failXml;
}
//generates validation success XML
private XmlDocument ValidationSucceeds(string PON)
{
XmlDocument succeedXml = new XmlDocument();
string succeedXmlString = "<PortOutValidationResponse>" +
"<Portable>true</Portable>" +
"<PON>" + PON + "</PON>" +
"</PortOutValidationResponse>";
succeedXml.LoadXml(succeedXmlString);
return succeedXml;
}
//define route that receives webhook
[HttpPost]
public XmlDocument Post([FromBody] XmlNode povData)
{
//move the XML list of numbers to an array
XmlNodeList numbers = povData.SelectNodes("//TelephoneNumber");
int countNumbers = numbers.Count;
string[] numbersArray = new string[countNumbers];
for (int i = 0; i < countNumbers; i++)
{
numbersArray[i] = numbers[i].InnerText;
}
//define an empty list that will store all the validation errors that get hit
List<string> errorTypes = new List<string>();
//run validation functions and add type of error to list if triggered
foreach (string number in numbersArray)
{
if (!CheckNumber(number))
{
errorTypes.Add("bad_number");
break;
}
}
if (povData.SelectNodes("//AccountNumber").Count < 1)
{
errorTypes.Add("no_account");
}
else if (!CheckAccountId(povData.SelectNodes("//AccountNumber")[0].InnerText))
{
errorTypes.Add("bad_account");
}
if (povData.SelectNodes("//Pin").Count < 1)
{
errorTypes.Add("no_pin");
}
else if (!CheckPin(povData.SelectNodes("//Pin")[0].InnerText))
{
errorTypes.Add("bad_pin");
}
//if errors, return failed validation XML. if no errors, return success XML. Passing the PON to the function here because that is required in the response XML.
if (errorTypes.Count > 0)
{
return ValidationFails(errorTypes, povData.SelectNodes("//PON")[0].InnerText);
}
return ValidationSucceeds(povData.SelectNodes("//PON")[0].InnerText);
}
}
}