I have a following POCO class. I don not want the parameterless constructor to be public.
public class FileDownloadRequest
{
//public FileDownloadRequest() { }
public FileDownloadRequest(int fileId, RepositoryFolderTypes fileType) //RepositoryFolderTypes is an enum, not a class
{
this.FileId = fileId;
this.FileType = fileType;
}
public int FileId { get; set; }
public RepositoryFolderTypes FileType { get; set; } //an enum
}
When I am trying a https://10.27.8.6/Files/DownloadFile?fileId=1&folderType=SRC
request to the following controller action, I get an error saying that no parameterless constructor exists for this object.
[HttpGet]
public async Task<HttpResponseMessage> DownloadFile([FromUri] FileDownloadRequest request)
{
}
Is it possible to have a non-public constructor, or is a public one absolutely required?
Also, while Patrick's answer is great and shows how to do it (in scenarios where this much effort really makes sense), I just add something I've noticed in another SO post.
Basically, mark the parameterless constructor as
[Obsolete("Comment to indicate its for binding only")]
and that will prevent others from accidentally calling the parameterless one. (Thus showing explicitly which properties are required by the request object)Yes, you can use any constructor you like, but you will have to do the model binding yourself then. The problem is in
DefaultModelBinder.CreateModel
, which uses a parameterless public constructor.You have to override the default model binder and create your own. If that is worth the time is up to you.
Steps to take:
CreateModel
;modelType
for some generic constraint which models you need to call the constructor with parameters on;Activator.CreateInstance(Type, Object[])
with the parameters. You could obtain their values from thebindingContext
;ModelBinder
attribute, or globally.Read more on custom bindings here.