Search code examples
c#asp.net-web-apiquery-stringasp.net-apicontroller

Split a string into three seperate parts


I have a URL string coming into an API e.g. c1:1=25.

*http://mysite/api/controllername?serial=123&c1:=25*

I want to split it into the channel name (c1), the channel reading number (1) after the colon and the value (25).

There are also occasions, where there is no colon as it is a fixed value such as a serial number (serial=123).

I have created a class:

public class UriDataModel
{
     public string ChannelName { get; set; }
     public string ChannelNumber { get; set; }
     public string ChannelValue { get; set; }
}

I am trying to use an IEnumerable with some LINQ and not getting very far.

var querystring = HttpContext.Current.Request.Url.Query;
querystring = querystring.Substring(1);           

var urldata = new UrlDataList
{
    UrlData = querystring.Split('&').ToList()
};

IEnumerable<UriDataModel> uriData =
        from x in urldata.UrlData
        let channelname = x.Split(':')
        from y in urldata.UrlData
        let channelreading = y.Split(':', '=')
        from z in urldata.UrlData
        let channelvalue = z.Split('=')
        select new UriDataModel()
        {
             ChannelName = channelname[0],
             ChannelNumber = channelreading[1],
             ChannelValue = channelvalue[2]
        };

        List<UriDataModel> udm = uriData.ToList();

I feel as if I am over complicating things here.

In summary, I want to split the string into three parts and where there is no colon split it into two.

Any pointers will be great. TIA


Solution

  • You can use regex. I think you switched the channel number and the colon in your example, so my code reflects this assumption.

    public static (string channelName, string channelNumber, string channelValue) ParseUrlData(string urlData)
    {
        var regex = new Regex(@"serial=(\d+)(&c(:\d+)?=(\d+))?");
        var matches = regex.Match(urlData);
        string name = null;
        string number = null;
        string value = null;
        if (matches.Success)
        {
            name = matches.Groups[1].Value;
            if (matches.Groups.Count == 5) number = matches.Groups[3].Value.TrimStart(':');
            if (matches.Groups.Count >= 4) value = matches.Groups[matches.Groups.Count - 1].Value;
        }
    
        Console.WriteLine($"[{name}] [{number}] [{value}]");
        return (name, number, value);
    }
    

    Then you can call it like this

    (var channelName, var channelNumber, var channelValue) = ParseUrlData("serial=123&c:1=25");
    (var channelName, var channelNumber, var channelValue) = ParseUrlData("serial=123&c=25");
    (var channelName, var channelNumber, var channelValue) = ParseUrlData("serial=123");
    

    and it'll return (and print)

    [123] [1] [25]
    [123] [] [25]
    [123] [] []