How about a custom model binder:
[ModelBinder(typeof(ServerConnectionModelBinder))]
public class ServerConnection
{
public ServerConnection(string connectionString)
{
if (string.IsNullOrEmpty(connectionString)) throw new ArgumentNullException(nameof(connectionString));
ConnectionString = connectionString;
}
public string ConnectionString { get; }
}
public class ServerConnectionModelBinder : IModelBinder
{
public bool BindModel(HttpActionContext actionContext, ModelBindingContext bindingContext)
{
if (bindingContext.ModelType != typeof(ServerConnection)) return false;
ValueProviderResult val = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
if (val is null) return false;
var server = val.RawValue as string;
if (server is null)
{
bindingContext.ModelState.AddModelError(bindingContext.ModelName, "Wrong value type");
return false;
}
var config = (IConfiguration)actionContext.Request.GetDependencyScope().GetService(typeof(IConfiguration));
if (config is null)
{
bindingContext.ModelState.AddModelError(bindingContext.ModelName, "Configuration service not registered");
return false;
}
string connectionString = config.GetConnectionString(server);
if (string.IsNullOrEmpty(connectionString))
{
bindingContext.ModelState.AddModelError(bindingContext.ModelName, $"Server '{server}' was not found.");
return false;
}
bindingContext.Model = new ServerConnection(connectionString);
return true;
}
}
[HttpGet("{id}")]
public async Task<IActionResult> Get(int id, ServerConnection server)
{
if (id < 0) return BadRequest();
if (server is null) return BadRequest();
var op = await _prodData.GetOperatorByID(id, server.ConnectionString);
...
If you don't want to check for
null
in every action, maybe a global action filter could help:
public class ValidateModelAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(HttpActionContext actionContext)
{
if (!actionContext.ModelState.IsValid)
{
actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.BadRequest, new
{
Message = "The data provided is not valid.",
ModelErrors = modelState
.Where(p => p.Value.Errors.Count != 0)
.ToDictionary(p => p.Key, p => p.Value.Select(e => new
{
Message = e.Exception is null ? e.ErrorMessage : e.Exception.Message,
StackTrace = e.Exception?.StackTrace,
})),
});
}
}
}
public class WebApiApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
GlobalConfiguration.Configuration.Filters.Add(new ValidateModelAttribute());
...
}
}
[HttpGet("{id}")]
public async Task<IActionResult> Get(int id, ServerConnection server)
{
if (id < 0) return BadRequest();
var op = await _prodData.GetOperatorByID(id, server.ConnectionString);
...