Testing?
Then create a simple unit test and test your API controller or your business layer classes directly. If you want to create an integration test or need a cleaner solution in production code read further.
Wrapping the API calls
This is just a disposable wrapper around the WebClient which can be easily reused.
public abstract class WebClientWrapperBase : IDisposable
{
private readonly string _baseUrl;
private Lazy<WebClient> _lazyClient;
protected WebClientWrapperBase(string baseUrl)
{
_baseUrl = baseUrl.Trim('/');
_lazyClient = new Lazy<WebClient>(() => new WebClient());
}
protected WebClient Client()
{
if (_lazyClient == null)
{
throw new ObjectDisposedException("WebClient has been disposed");
}
return _lazyClient.Value;
}
protected T Execute<T>(string urlSegment)
{
return JsonConvert.DeserializeObject<T>(Client().DownloadString(_baseUrl + '/' + urlSegment.TrimStart('/')));
}
~WebClientWrapperBase()
{
Dispose(false);
}
public void Dispose()
{
Dispose(false);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (_lazyClient != null)
{
if (disposing)
{
if (_lazyClient.IsValueCreated)
{
_lazyClient.Value.Dispose();
_lazyClient = null;
}
}
// There are no unmanaged resources to release, but
// if we add them, they need to be released here.
}
}
}
Creating a "strongly typed proxy":
class StudentDashboardClient : WebClientWrapperBase
{
public StudentDashboardClient()
: base("http://localhost/webapi/api/StudentDashboard/")
{
//just for compatibility
}
public StudentDashboardClient(string baseUrl)
: base(baseUrl)
{
}
public User GetUserRecord(string userName)
{
return Execute<User>("GetUserRecord?userName=" + userName);
}
}
And then passing to your controllers where it's needed:
public class HomeController : Controller
{
private readonly StudentDashboardClient _studentDashboardClient;
public HomeController(StudentDashboardClient studentDashboardClient)
{
_studentDashboardClient = studentDashboardClient;
}
public ActionResult Index()
{
return View(_studentDashboardClient.GetUserRecord("jBob"));
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
_studentDashboardClient.Dispose();
}
base.Dispose(disposing);
}
}
Note that the controller now have a parameterless constructor so you will need a solution to instantiate controllers this way for example a DI framework with MVC support like Ninject.
What you gain? Cleaner code.