HTTP状态码转换为易读的字符串

11
HttpWebResponse response = (HttpWebResponse)await request.GetResponseAsync();
HttpStatusCode statusCode = response.StatusCode;

在这段代码中,statusCode.ToString() 返回例如 "BadRequest",但我需要 "Bad Request"

我看到了关于 response.ReasonPhrase 的文章,但那不是我需要的并且它不被 HttpWebResponse 支持,只被来自 HttpClientHttpResponseMessage支持。

另一个反对 Regex.Replace 解决方案的例子:(414) RequestUriTooLong -> Request-Uri Too Long


2
如果远程服务器返回418代码怎么办?你期望它转换成什么? - DavidG
1
你试图解决的问题是什么,你已经决定解决方案需要使用“Bad Request”而不是“BadRequest”? - Daniel Mann
2
你有检查过 HttpWebResponse.StatusDescription 吗? - Panagiotis Kanavos
1
@Vitaliy,程序显示了StatusCode和StatusDescription。你有检查过吗?即使它是空的,你也可以使用类似Humanizer这样的工具将枚举值转换为可读名称。但是如果状态码在枚举中未定义,则无法执行此操作。 - Panagiotis Kanavos
@dlatikay,这些是完全不同的问题。 - Vitaliy
显示剩余6条评论
3个回答

17
根据参考源代码,您可以通过对静态类进行简单调用,根据状态码获取英文状态描述。
int code = 400;

/* will assign "Bad Request" to text */
var text = System.Web.HttpWorkerRequest.GetStatusDescription(code);

文本定义在100-507范围内,对于特殊代码如418和506,返回空字符串。


1
这不是已经通过StatusDescription属性可用了吗? - Panagiotis Kanavos
确实。因此,它为仅具有状态代码的人回答了问题,而 OP 则拥有完整的 HttpWebResponse 实例。 - Cee McSharpface

5

HttpStatusCode 是一个包含驼峰式成员名称的 enum
您可以使用这个一行代码将驼峰式命名之间加上空格以满足您的需求:

return Regex.Replace(statusCode.ToString(), "(?<=[a-z])([A-Z])", " $1", RegexOptions.Compiled);

0

这里,我从一个字符串实用类中提取了这个。可能有点过度设计,但它是一个有用的东西。使用ToTitleCase扩展方法。

/// <summary>
/// A dictionary that holds the collection of previous title case
/// conversions so they don't have to be done again if needed more than once.
/// </summary>
private static Dictionary<string, string> _prevTitleCaseConversions = new Dictionary<String, String>();

/// <summary>
/// A collection of English words that should be lower-case in title-cased phrases.
/// </summary>
private static List<string> _englishTitleCaseLowerCaseWords = new List<string>() {"aboard", "about", "above", "across", "after",
    "against", "along", "amid", "among", "anti", "around", "is", "as", "at", "before", "behind", "below",
    "beneath", "beside", "besides", "between", "beyond", "but", "by", "concerning", "considering",
    "despite", "down", "during", "except", "excepting", "excluding", "following", "for", "from", "in",
    "inside", "into", "like", "minus", "near", "of", "off", "on", "onto", "opposite", "outside", "over",
    "past", "per", "plus", "regarding", "round", "save", "since", "than", "through", "to", "toward",
    "towards", "under", "underneath", "unlike", "until", "up", "upon", "versus", "via", "with", "within", "without",
    "and", "but", "or", "nor", "for", "yet", "so", "although", "because", "since", "unless", "the", "a", "an"};

/// <summary>
/// Convert the provided alpha-numeric string to title case.  The string may contain spaces in addition to letters and numbers, or it can be
/// one individual lowercase, uppercase, or camel case token.
/// </summary>
/// <param name="forValue">The input string which will be converted.  The string can be a 
/// normal string with spaces or a single token in all lowercase, all uppercase, or camel case.</param>
/// <returns>A version of the input string which has had spaces inserted between each internal "word" that is 
/// delimited by an uppercase character and which has otherwise been converted to title case, i.e. all 
/// words except for conjunctions, prepositions, and articles are upper case.</returns>
public static string ToTitleCase(this string forValue)
{
    if (string.IsNullOrEmpty(forValue)) return forValue;

    if (!Regex.IsMatch(forValue, "^[A-Za-z0-9 ]+$"))
        throw new ArgumentException($@"""{forValue}"" is not a valid alpha-numeric token for this method.");

    if (_prevTitleCaseConversions.ContainsKey(forValue)) return _prevTitleCaseConversions[forValue];

    var tokenizedChars = GetTokenizedCharacterArray(forValue);
    StringBuilder wordsSB = GetTitleCasedTokens(tokenizedChars);
    string ret = wordsSB.ToString();
    _prevTitleCaseConversions.Add(forValue, ret);
    return ret;
}

/// <summary>
/// Convert the provided string such that first character is 
/// uppercase and the remaining characters are lowercase.
/// </summary>
/// <param name="forInput">The string which will have 
/// its first character converted to uppercase and 
/// subsequent characters converted to lowercase.</param>
/// <returns>The provided string with its first character 
/// converted to uppercase and subsequent characters converted to lowercase.</returns>
private static string FirstUpper(this string forInput)
{
    return Alter(forInput, new Func<string, string>((input) => input.ToUpperInvariant()), new Func<string, string>((input) => input.ToLowerInvariant()));
}

/// <summary>
/// Return an array of characters built from the provided string with 
/// spaces in between each word (token).
/// </summary>
private static ReadOnlyCollection<char> GetTokenizedCharacterArray(string fromInput)
{
    var ret = new List<char>();
    var tokenChars = fromInput.ToCharArray();
    bool isPrevCharUpper = false;
    bool isPrevPrevCharUpper = false;
    bool isPrevPrevPrevCharUpper = false;
    bool isNextCharUpper = false;
    bool isNextCharSpace = false;

    for (int i = 0; i < tokenChars.Length; i++)
    {
        char letter = tokenChars[i];
        bool addSpace;
        bool isCharUpper = char.IsUpper(letter);

        if (i == 0) addSpace = false; // no space before first char.
        else
        {
            bool isAtLastChar = i == tokenChars.Length - 1;
            isNextCharUpper = !isAtLastChar && char.IsUpper(tokenChars[i + 1]);
            isNextCharSpace = !isAtLastChar && !isNextCharUpper && tokenChars[i + 1].Equals(' ');
            bool isInAcronym = (isCharUpper && isPrevCharUpper && (isAtLastChar || isNextCharSpace || isNextCharUpper));
            addSpace = isCharUpper && !isInAcronym;
        }

        if (addSpace) ret.Add(' ');
        ret.Add(letter);
        isPrevPrevPrevCharUpper = isPrevPrevCharUpper;
        isPrevPrevCharUpper = isPrevCharUpper;
        isPrevCharUpper = isCharUpper;
    }

    return ret.AsReadOnly();
}

/// <summary>
/// Return a string builder that will produce a string which contains
/// all the tokens (words separated by spaces) in the provided collection
/// of characters and where the string conforms to title casing rules as defined above.
/// </summary>
private static StringBuilder GetTitleCasedTokens(IEnumerable<char> fromTokenChars)
{
    StringBuilder wordsSB = new StringBuilder();
    var comparer = StringComparer.Create(System.Globalization.CultureInfo.CurrentCulture, true);
    var words = new string(fromTokenChars.ToArray()).Split(' ');
    bool isFirstWord = true;

    foreach (string word in words)
    {
        if (word.Length == 0) continue;
        if (wordsSB.Length > 0) wordsSB.Append(' ');
        bool isAcronym = word.Length > 1 && word.All((c) => char.IsUpper(c));
        string toAppend;

        // leave acronyms as-is, and lower-case all title case exceptions unless it's the first word.
        if (isAcronym) toAppend = word;
        else if (isFirstWord || !_englishTitleCaseLowerCaseWords.Contains(word, comparer)) toAppend = word.FirstUpper();
        else toAppend = word.ToLower();

        wordsSB.Append(toAppend);
        isFirstWord = false;
    }

    return wordsSB;
}

/// <summary>
/// Convert the provided string such that first character is altered using 
/// <paramref name="firstCharAlterationFunction"/> and the remaining characters
/// are altered using <paramref name="remainingCharsAlterationFunction"/>.
/// </summary>
/// <param name="forInput">The string which will have 
/// its first character altered using <paramref name="firstCharAlterationFunction"/> and 
/// subsequent characters altered using <paramref name="remainingCharsAlterationFunction"/>.</param>
/// <param name="firstCharAlterationFunction">The function which will
/// be used to alter the first character of the input string.</param>
/// <param name="remainingCharsAlterationFunction">The function which
/// will be used to ever character in the string after the first character.</param>
/// <returns>The provided string with its first character 
/// altered using <paramref name="firstCharAlterationFunction"/> and 
/// subsequent characters altered using <paramref name="remainingCharsAlterationFunction"/>.</returns>
private static string Alter(string forInput, Func<string, string> firstCharAlterationFunction, Func<string, string> remainingCharsAlterationFunction)
{
    if (string.IsNullOrWhiteSpace(forInput)) return forInput;
    if (forInput.Length == 1) return firstCharAlterationFunction(forInput);
    return firstCharAlterationFunction(forInput[0].ToString()) + remainingCharsAlterationFunction(forInput.Substring(1));
}

你能给它规则吗?我发现大多数解决方案都不符合我的特定业务需求。 - rory.ap
我非常确定StatusDescription已经包含了OP想要的内容。即使使用Humanizer可能有点过度 - 并且比这段代码要大得多。 - Panagiotis Kanavos

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接