2

I have a string that is used in a few places.

string portalLoginPath = $"{Request.Scheme}{Uri.SchemeDelimiter}{Request.Host}/Account/Login";

I was thinking of creating a static class with a string const to store it.

public static class StringConsts{
public const string portalPath = $"{Request.Scheme}{Uri.SchemeDelimiter}{Request.Host}/Account/Login";
}

Is there a cleaner way to do this?

I'm building in ASP.NET Core MVC

  • 1
    One thing to keep in mind when making this decision is how difficult you're making it to internationalize the application. If the German market opens up to you how much rewriting do you want to do just to use the translated versions of your strings? Is YAGNI good enough here or is it worth at least thinking about it? – candied_orange Dec 15 '18 at 0:59
  • 1
    The first question you should ask is: Do I really need to use it in that many places? – Frank Puffer Dec 15 '18 at 7:08
7

In C# a string preceded by a $ is an interpolated string.

An interpolated string is a construct that both

  • declares a string literal, and,
  • asks the compiler to interpolate variables names/expressions within the string.

These two cannot be separated: I know of no way to declare the string outside of the context where the compiler will find the variables, and no way to ask for interpolation of an externally stored string in the context of a scope that has the variables of interest.

Thus, there's no way to put a $"{}" type string anywhere but within the code that uses it.


The only way to put the string elsewhere (other than embedded in the code) is to forgo interpolation.  In your case all that would be left is "/Account/Login", leaving you to use the expressions in a string.Format statement.

  • 1
    With this response in mind, I'd say a static class with a static method taking your Request and Uri objects as input is probably what you're looking for. – Turksarama Dec 15 '18 at 8:27
4

A static class is a good idea. One thing to be careful of is that class getting cluttered with a bunch of strings, then you might have little context of what the string is actually used for.

One way to solve this is have the context in the name of the class. Instead of StringConsts, maybe call this PortalConsts (Or whatever makes the most sense). This way you can organize your strings by class so it doesn't get disorganized.

1

Since what you want is to interpolate, what you're describing is not a constant but a function. In that case you could use a delegate:

public delegate string PortalPathFormatFunction(string scheme, string delimiter, 
    string host);

The reason I would use a delegate instead of just Func<string, string, string, string> is that it identifies the purpose of a function and disambiguates it from other functions with the same signature.

You could then implement it something like this (naming is hard)

public static class PathFormats
{
    public static PortalPathFormatFunction GetPortalPath { get; } 
        = (scheme, delimiter, host) => $"{scheme}{delimiter}{host}/Account/Login";
}

or just

public static string GetPortalPath(string scheme, string delimiter, string host) => 
    $"{scheme}{delimiter}{host}/Account/Login";

I prefer the first one because it specifies that the function must correspond to the delegate, like a class implementing an interface. If someone changes the function so that it no longer matches the delegate, I want the compiler error there, telling them not to do that, as opposed to somewhere else.

0

You shouldn't just be thinking of this as "a string that needs to be shared" - "strings" are a technical definition, not part of your OO or domain model. Who, in your system, would know the portal login url? Probably some sort of LoginManager, or perhaps PortalConnection component, which could also expose this path if necessary.

Of course, with this PortalConnection, you might see that it makes more sense, from the perspective of encapsulation, to not expose that string path, but instead expose a Login() method on your PortalConnection which handles logging into the portal in one place, instead of exposing the path, which is an implementation detail - it shouldn't be the responsibility of every component in your system to know how to login.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.