I was wondering if you can make a MVC webservice that only has HTTP POST methods.
For instance:
I use Selenium to open a page : http://localhost/main.html from .EXE application.
then my MVC app looks like this:
[HttpGet]
public ActionResult main()
{
return View();
}
[HttpPost]
public ActionResult Final(USER user)
{
saveUSER(user);
return null;
}
I just don't want MVC to open another page that the one that selenium used. I used to do this with an HttpWebRequest to the GET method, but even if I returned null, it would open a blank page AND then work out the rest of the logic.
The better way to test Post methods, services and repositories in a MVC Application is using functional or unit tests. There are nice frameworks that would help you to develop these tests.
I've been using Nunit to develop automated test in my work and in my own projects, the framework provide me the tools to develop functional and unit tests and runs all selenium integration tests inside him.
Related
Thanks for your time , I have a simple question, in an asp.net MVC application, inside controllers is it possible that along with some methods returning View (ActionMethods) other could act as (or return) Json as a Web API (could be called from external apps).
Just trying to do a proper separations, hence trying to understand.
Thanks much.
You can make an action function like an API. Try something like the this.
// Controller/Action
[HttpGet]
public ActionResult IAmSpecial()
{
if (Request.IsAjaxRequest())
{
string[] objects = new string[] { "Foo", "Bar" };
return Json(objects);
}
return View();
}
This will return the IAmSpecial view if you browse to {domain}/{Controller}/IAmSpecial while it will return a JSON result if you use an AJAX Http Get request on the same url.
while it is possible to have controller methods which return Json data only, there are a number of considerations when you want to expose that data outside of the UI app.
Since you have an MVC app, I expect you have users and a way to login. Your controllers would more than likely be secured in some way, which works for the internal users of the application. Now you want to add one method which effectively becomes an API, available outside of the application and calls to it will have to be authenticated somehow.
What I would suggest is to split this up. You can create a separate project, which is a WebAPI one, in the same solution. The code which prepares the data can live in a class library you can then reference in both your MVC and WebAPI projects.
Your MVC app can call it and then return a view with that data, the WebAPI calls it and simply returns the data. You can now decide on a way of securing your API, maybe using Identity Server or some other way and you can keep adding things to it, without affecting the UI layer.
Your second option is to make the MVC app use the API when it needs to retrieve data, so both your public clients and UI use the same thing.
Whichever option you use, the idea is to not duplicate anything and at the same time provide the security layers you need.
I am pretty new in .NET (I came from Java and Spring framework) and I never worked on the cloud untill now.
At the moment I started to work on a new .NET project deployed in Azure. I know that I can debug it from Visual Studio using the Cloud Explorer view but I have a doubt about how can I perform unit test in the cloud.
I try to explain better with an example. Into my project I have this controller class:
namespace MyProject.Controllers
{
/**
* Classe controller che implementa le operazioni per protocollare una mail
*/
public class MailProtocolloController : ApiController
{
private String urlBaseProtocolloApi = "http://myserver.westeurope.cloudapp.azure.com:8081/myApi";
public void getAooList()
{
string jsonRequest = urlBaseProtocolloApi + "/api/myresource/GetDepartmentsList";
CredentialCache credCache = new CredentialCache();
credCache.Add(new Uri(jsonRequest), "NTLM", CredentialCache.DefaultNetworkCredentials);
HttpWebRequest spRequest = (HttpWebRequest)HttpWebRequest.Create(jsonRequest);
spRequest.Credentials = credCache;
spRequest.UserAgent = "Mozilla/4.0+(compatible;+MSIE+5.01;+Windows+NT+5.0";
spRequest.Method = "GET";
spRequest.Accept = "application/json;odata=verbose";
HttpWebResponse endpointResponse = (HttpWebResponse)spRequest.GetResponse();
string sResult;
}
}
}
Ok, I know that at the moment this API is returning nothing (void), it is still in an embryonic state and I have to change it.
At the moment the only thing that I want to do is to test it using unit test to check if the sResult property contains the result.
Questions:
1) To execute my application it have to be deployed in the cloud (because this API call a REST API that have to be on the same environment, infact I am attaching the credentisial using the CredentialCache class. Can I deploy this app on the cloud and from here performing my unit test? (something like perform debug in the cloud using the Cloud Explorer view.
2) What have I to do to create unit test into a .NET project? (In Java I simply create a class importing JUnit)
1.) If you have to test it in the cloud, it isn't an unit test, it is an integration test! For integration tests I recommend you postman and the postman runner (newman). You can define your rest calls in postman with an JS scripts to test the responses and you can call the defined test with the CLI-Tool newman to automate this.
2.) There are 2 possibilities in C# for Unit Test MS Test and NUnit. Here is a comparison matrix between the two to decide which matches the best:
http://www.anarsolutions.com/automated-unit-testing-tools-comparison/
If you want somethin similar to JUnit than I think NUint is the best for you:
NUnit is an open-source unit testing framework for Microsoft .NET. It serves the same purpose as JUnit does in the Java world
For example with MS Test you have to add the MSTest Nuget package, define your class with the annotation [TestClass] and your test method with the annotaion [TestMethod] afterwards you can use the Assert commands in your test method i.e.
[TestClass]
public class MyTestClass
{
[TestMethod]
public void MyTest_Successful()
{
Assert.IsTrue(/*Something true*/ true);
}
}
I am following this tutorial on how to create a simple database web application with ASP.NET MVC. I am having a problem with the 2nd Create controller method in the home controller (in Listing 4). Specifically, the error - when the web app is built - is with the AddToMovieSet method that actually saves the entries to the database.
It is worth noting that I am using VS 2016, whereas the tutorial uses a much older version (2008); this might be the reason to the problem. But, nevertheless, what is the code for this Create controller method?
This is the code in the Create action method in the home controller:
public ActionResult Create(Movie movieToCreate)
{
if (!ModelState.IsValid)
return View();
_db.AddToMovieSet(movieToCreate);
_db.SaveChanges();
return RedirectToAction("Index");
}
Make sure you have proper view created for this action method. Else create view or return view explicitly with name.
I'm implementing a REST Web API. I'm using the examples from Adam Freeman's Pro ASP.NET MVC5 as a starting point but adapting it into the Web API way of doing it.
The below is my code:
public class AdminController : ApiController
{
private IUserRepository _repository;
public AdminController(IUserRepository repository)
{
_repository = repository;
}
public ActionResult Index()
{
return View(_repository.Users);
}
}
In the book, AdminController implemented Controller not ApiController, but if I do that then I get errors about there being no parameterless constructor. I need the constructor to take parameters so that I can inject the dependencies. So that's why I changed to ApiController but now it won't recognise View.
What do I need to use instead of View for an ApiController?
I did find this question but the answer was basically "you don't need to use an ApiController here, just use Controller" so that didn't help me.
You are having two different problems. Let's solve them separately.
1. Do I need to use ApiController or Controller?:
Someone already answered this here: Difference between ApiController and Controller in ASP.NET MVC.
The first major difference you will notice is that actions on Web API
controllers do not return views, they return data.
ApiControllers are specialized in returning data. For example, they
take care of transparently serializing the data into the format
requested by the client.
So, if you want to return a View you need to use the simple ol' Controller. The WebApi "way" is like a webservice where you exchange data with another service (returning JSON or XML to that service, not a View). So whenever you want to return a webpage (View) for a user you don't use the Web API.
In other words, the Web API is about returning data to another service (to return a JSON or XML), not to a user.
2. But if I use Controller then I get "parameterless constructor" errors.
Okay, now we've got to your real problem. Don't try to reinvent the wheel and fight with ASP.NET about doing dependency injection! A tool already exists to resolve dependency injection and sort out the "parameterless constructor" error: Ninject.
If you're already using Ninject and still getting that error, you're doing something wrong with Ninject. Try to repeat the installation and configuration steps, and see some tutorials or questions about parameterless error with Ninject use
An API controller is a controller which provides a RESTful response. You cannot return a view from it. Instead of doing that, consider returning a response (values) which forces the client that asks for an action to redirect to another controller (passing arguments if necessary) to return a view.
Your case does not look like you need an API; in this case just try this (change what you inherit):
public class AdminController : Controller
{
private IUserRepository _repository;
public AdminController(IUserRepository repository)
{
_repository = repository;
}
public ActionResult Index()
{
return View(_repository.Users);
}
}
I will try to explain what an API should do anyway. A web API should return just information. An HTTP response about what the action should do.
For example, to create a new customer, an API should have a method (decorated with POST) to get information from a client application (could be anything: web, windows, mobile, windows service, etc.). This information should be processed by the API (or other layers in a possible architecture) and return an HTTP status code, for example 200 - OK if it was fine or 400 - Bad Request if an error happened. So, when I said you should consider returning information, you could just return a DTO object to provide a result.
Both types of project use MVC principles, but they are used in a different context. Take a look at these articles:
Web Api 2.0 Tutorial
Difference between MVC and WEB API
Also take a look at the ASP.NET website about how they work:
ASP.NET WEB API
ASP.NET MVC
Use Controller to render your normal views. ApiController action only return data that is serialized and sent to the client.
But still you want to render view from APIcontroller, then there may be a another way, click on below link for reference :
https://aspguy.wordpress.com/2013/09/10/web-api-and-returning-a-razor-view/
I want to confirm that my "HomeController" class is being selected by the route I've created. So I have a test like this:
[TestMethod]
[UrlToTest("http://localhost:14478/home")]
[HostType("ASP.NET")]
[AspNetDevelopmentServerHost("$(SolutionDir)\\MvcBuildApp")]
public void MyTest()
{
System.Diagnostics.Debugger.Break();
RouteCollection routes = new RouteCollection();
MvcApplication.RegisterRoutes(routes);
MvcApplication.RegisterGlobalFilters(GlobalFilters.Filters);
//This fetches DefaultControllerFactory (for now, anyway...)
var factory = ControllerBuilder.Current.GetControllerFactory();
//mock a context...
var httpContext = CreateHttpContext("http://localhost:14478/home", "GET");
RouteData route = routes.GetRouteData(httpContext);
var ctrlInstance = factory.CreateController(new RequestContext(httpContext, route), (string)route.Values["controller"]);
//ASSERT the instance is of type "HomeController"
//...
}
It fails, saying that 'http://localhost:14478/home' completed successfully without running the test.
I noticed that in the VS output window, there is also this message No connection could be made because the target machine actively refused it 127.0.0.1:14478. I figured Cassini must not be active. So I chose to launch the site being tested (ctrl+F5) before launching the unit test. It then changed the VS output to this:
WebTestAdapter.ConnectToHostAdapter: unexpected exception occured.
Microsoft.VisualStudio.TestTools.HostAdapters.AbortTestExecutionException:
Error in the application. at
Microsoft.VisualStudio.TestTools.HostAdapters.WebTestAdapter.ConnectToHostAdapter()
To try to resolve this, I've followed the advice of these articles:
Debug while running a test in ASP.NET solution
Unit Tests for ASP.NET web services: this discusses the "completed successfully without running a test" error.
Configuring ASP.NET Unit Tests: I got the $(SolutionDir) idea from this article.
...but I still get the error no matter what I do. Suggestions?
UPDATE/CLARIFICATION
This question is not about testing MVC routes. The purpose of this question is to discover how to make ASP.NET MVC properly initialized to allow more "in depth" automated testing. I have chosen a "route testing" scenario, against the DefaultControllerFactory, merely as an example. In this example, the DefaultControllerFactory does not behave properly unless ASP.NET MVC is properly initialized.
This is a common requirement when testing MVC applications, and lucky you, there is a framework that will simplify your life when testing MVC controllers:
The tools is:
http://mvccontrib.codeplex.com/
And as an example you can create tests with just one line:
"~/".ShouldMapTo<HomeController>(controller => controller.Index());
As a reference:
http://geekswithblogs.net/thomasweller/archive/2009/11/02/unit-testing-asp.net-mvc-routes.aspx
http://www.arrangeactassert.com/how-to-unit-test-asp-net-mvc-controllers/
You may be interested in reviewing Steve Sandersons MVC testing framework. If you download the source you will have a great example on how to initialize the MVC framwork:
http://blog.codeville.net/2009/06/11/integration-testing-your-aspnet-mvc-application/