I have a solution with two project , one is my webapi service and another is my mvc for project . I am calling the service from my controller. My service has GET,POST,PUT all methods. In my view i am using a submit button and which calles the post controller method which in turn call my service . Here the issue i am facing is it is calling always the GET method. I want to fire the POST method in my service
controller post method
[HttpPost]
public ActionResult Create(Test test)
{
if (ModelState.IsValid)
{
Test objTest = MyService.Create(test);
if (objTest == null)
{
return HttpNotFound();
}
return RedirectToAction("Index");
}
}
Here calls the service
**public Test Create(Test test)
{
string uri = baseUri + "Test/";
using (HttpClient httpClient = new HttpClient())
{
Task<HttpResponseMessage> response = httpClient.PostAsJsonAsync(uri, new StringContent(JsonConvert.SerializeObject(Test)));
return JsonConvert.DeserializeObjectAsync<Test>(response.Result.Content.ReadAsStringAsync().Result).Result;
}
}**
This is the post
**// POST api/Test
public HttpResponseMessage PostTest(test test
{
if (ModelState.IsValid)
{
db.Test.Add(test);
db.SaveChanges();
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.Created, test);
response.Headers.Location = new Uri(Url.Link("DefaultApi", new { id = test.TestID }));
return response;
}
else
{
return Request.CreateResponse(HttpStatusCode.BadRequest);
}
}
****************
**// GET api/Test
public IEnumerable<Test> GetTest()
{
var tests= db.Tests;
return tests.AsEnumerable();
}**
It always calls the above Get method . I am completely new to web api service. Can some one guide me with proper way , where i am wrong. I am not using any ajax to call post method.
Well, look at the method you're using:
httpClient.GetStringAsync(uri);
Get does exactly what the name implies. It makes a GET request to the resource. If you want to use a different HTTP verb, use one of the other methods available.
For example:
httpClient.PostAsync(uri, someContentObject);
Or, using HttpClientExtensions:
httpClient.PostAsJsonAsync(uri, test);
This is how you do a POST with some data.It's similar to the GET request but in this case since you want to send a POST this will be aplicable. Also notice its simple to add POST data (when compared with HttpWebRequest)
httpClient.PostAsync(uri, new StringContent(data));
Related
Trying to put, method with two parametres, object in body and bool in url.
but there is no connection between the service and controller.
controller:
[AllowAnonymous]
[HttpPut]
[Route("putQuestionDifficulty/{id}")]
[ResponseType(typeof(Question))]
public IHttpActionResult PutQuestionDifficulty([FromBody] Question question, [FromUri] bool id)
{
var myquestion = db.Questions.Find(question);
if (id)
{
myquestion.Difficulty++;
}
else myquestion.Difficulty--;
db.SaveChanges();
return Ok(question);
}
service :
putQuestionDifficulty(question: Question, id: boolean){
return this.http.put<Question>(`${this.baseUrl}/putQuestionDifficulty/${id}`,question);
}
You need to call your service and subscribe it to read the data
Call you putQuestionDifficulty method with specific prams
Try something like this in your component
this.putQuestionDifficulty(question, id).subscribe((res) => {
console.log(res);
});
Hope this will help you - Happy coding :)
I am using Castle Windsor as DI and using reposity to access and implement the data layers.
As I have implemented all the data access layer in my repo, it is time to call those methods in my API controller. SO I have 'getAllReportsByClient method' and 'CreateReport' POST method. So, in order to test if some methods are working without actually implementing the view and AJAX call, how can I insert sample data using my 'Create Report' method?
The method from repo is below:
public void CreateReport(TReportHeaderModel model)
{
using (var connection = new TReportEntitiesConnection())
{
connection.THeader.Add(new THeader()
{
ClientID=model.ClientID,
ID=model.ID,
THeaderTitle=model.THeaderTitle,
RowNumber=model.RowNumber
});
foreach (var d in model.TReports)
{
connection.TReport.Add(new TReport()
{
ID=d.ID,
TReportName=d.TReportName,
URL=d.URL,
RowNumber=d.RowNumber,
});
}
connection.SaveChanges();
}
throw new NotImplementedException();
}
The below is HTTPPOST createReport call in Controller:
[HttpPost]
public ActionResultModel CreateReport([FromBody] TReportHeaderModel model)
{
try
{
_tReportingService.CreateReport(model);
return new ActionResultModel() //return void, must not be followed by object expression
{
Success = true,
Message = "Report Successfully Created."
};
}
catch (Exception ex)
{
return new ActionResultModel()
{
Success = false,
Message = "Report not created.",
Obj=ex.Message
};
}
}
You could use Postman(https://www.getpostman.com/) or Fiddler(www.telerik.com/fiddler) to emulate the request. Even better, you could write a test using a testing framework.
I am working on a MVC Web App which is calling a Web API. In my Create (POST) method, a user will enter email addresses of some users in the database. I have a check to enter the email only if the email does not already exist in the database or not. If it already exists, I want to be able to show an error message to the user "Email already exists".
I thought HttpStatusCode.NotFound, "Email exists already." would work, but I think it will only show in PostMan. How can I show it on the MVC side with like ViewBag.ErrorMessage?
API
public IHttpActionResult PostApprovedUsers(ApprovedUsers approvedUsers)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
if (!db.ApprovedUsers.Any(u => u.Email == approvedUsers.Email))
{
db.ApprovedUsers.Add(approvedUsers);
db.SaveChanges();
}
else
{
return Content(HttpStatusCode.NotFound, "Email exists already.");
}
return CreatedAtRoute("DefaultApi", new { id = approvedUsers.Email }, approvedUsers);
MVC Create
public ActionResult Create([Bind(Include = "Email,FirstName,LastName")] ApprovedUsers approvedUsers)
{
using (WebClient client = new WebClient())
{
token = Session.GetDataFromSession<string>("access_token");
client.Headers.Add("authorization", "Bearer " + token);
client.UploadValues(apiUrl, "POST", new NameValueCollection()
{
{ "Email", approvedUsers.Email },
{ "FirstName",approvedUsers.FirstName },
{ "LastName",approvedUsers.LastName }
});
}
return RedirectToAction("Index");
}
The main problem with what you were seeing is that you were not in fact doing anything with the return value of webclient. That is ok though, since based on our discussion everything is in the same project and that would not be how you would want to do this using ASP.NET MVC and Web API.
Since these are all in the same project, we do want to combine common functionality but not within a controller. The DB service should be abstracted away into a seperate project - or class - and then injected into both controllers using some form of IoC Container. There are a couple of options available and I personally usually use Ninject for my .NET projects.
Assuming you have that functionality your MVC Controller and API controller should then both program against that abstraction. Interface based programming is how .NET works best.
With that in mind your new API controller would look something like this:
public IHttpActionResult PostApprovedUsers([Bind(Include="Email, FirstName, LastName")]ApprovedUser approvedUser)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
if (_db.UserExists(approvedUser))
{
return Content(HttpStatusCode.NotFound, "Email exists Already");
}
_db.AddUser(approvedUser);
return CreatedAtRoute("DefaultApi", new {id = approvedUser.Email}, approvedUser);
}
Where _db is the service that gets injected into the controller. Please not how common functionality such as checking to see if a user exists and adding a user are wrapped behind the abstraction:
public interface IMyFakeDbService
{
IQueryable<ApprovedUser> ApprovedUsers { get; }
int RemoveUser(ApprovedUser user);
int RemoveUser(string email);
bool UserExists(ApprovedUser user);
void AddUser(ApprovedUser user);
}
This then brings us to your MVC Controller. The same principle applies; since all the common functionality is in the db service just inject that into the controller instead of calling the API controller. You will see that you can use ModelState.AddModelError here to pass information back into the view.
public ActionResult Create()
{
return View();
}
[HttpPost]
public ActionResult Create([Bind(Include = "Email, FirstName, LastName")]ApprovedUser user)
{
if (ModelState.IsValid)
{
if (!_db.UserExists(user))
{
_db.AddUser(user);
return RedirectToAction("Index");
}
ModelState.AddModelError("","A user with that email already exists");
}
return View();
}
Finally
I made a public git repo with a complete project here
The DB calls should be async. You are wasting server resources if not
If you want to learn MVC real quick I would suggest Pro ASP.NET MVC 5 and Pro ASP.NET Web API2
I always use Ok<T>, where T is a model I defined which have 3 variables, one will identify the status (true, false) and one will be a string message, and one will have data type of List<object> which I need to receive at end point, then you can modify the error message as you want
in your case instead of this
return BadRequest(ModelState);
I will replace it with something like this
return Ok<MyResponse>(new MyResponse{ Message = "Error Message Here", Status = false});
then once you get your content you can desirialize it into your object
MyResponse response = new MyResponse();
HttpResponseMessage response = await client.GetAsync(path);
// ok will return success status code, but you will depend on your status to know if it was success or error happened
if (response.IsSuccessStatusCode)
{
// Desirialize your result
response = await response.Content.ReadAsAsync<MyResponse>();
}
// then get the message,
if(response.Status)
{
//it was fine, return something ..
}
else {
// Error happened, get your error message and disaply it, if you want as viewbag
ViewBag.ErrorMessage = response.Message;
// do something
}
I'm very new to ASP.NET 4.0 Web API. Can we redirect to another URL at the end of the POST action?, something like ... Response.Redirect(url)
Actually I upload file from a MVC application (say www.abcmvc.com) through Web API (say www.abcwebapi.com/upload)
Here upload is the POST action. I post a multi-part form to Web API upload controller's post action. After uploading I would like to redirect back to www.abcmvc.com.
Is this possible?
Sure:
public HttpResponseMessage Post()
{
// ... do the job
// now redirect
var response = Request.CreateResponse(HttpStatusCode.Moved);
response.Headers.Location = new Uri("http://www.abcmvc.com");
return response;
}
Here is another way you can get to the root of your website without hard coding the url:
var response = Request.CreateResponse(HttpStatusCode.Moved);
string fullyQualifiedUrl = Request.RequestUri.GetLeftPart(UriPartial.Authority);
response.Headers.Location = new Uri(fullyQualifiedUrl);
Note:
Will only work if both your MVC website and WebApi are on the same URL
[HttpGet]
public RedirectResult Get()
{
return RedirectPermanent("https://www.google.com");
}
You can check this
[Route("Report/MyReport")]
public IHttpActionResult GetReport()
{
string url = "https://localhost:44305/Templates/ReportPage.html";
System.Uri uri = new System.Uri(url);
return Redirect(uri);
}
[HttpGet]
public RedirectResult Get() {
return new RedirectResult("https://example.com");
}
I am writing an application that is accepting POST data from a third party service.
When this data is POSTed I must return a 200 HTTP Status Code.
How can I do this from my controller?
In your controller you'd return an HttpStatusCodeResult like this...
[HttpPost]
public ActionResult SomeMethod(...your method parameters go here...)
{
// todo: put your processing code here
//If not using MVC5
return new HttpStatusCodeResult(200);
//If using MVC5
return new HttpStatusCodeResult(HttpStatusCode.OK); // OK = 200
}
200 is just the normal HTTP header for a successful request. If that's all you need, just have the controller return new EmptyResult();
You can simply set the status code of the response to 200 like the following
public ActionResult SomeMethod(parameters...)
{
//others code here
...
Response.StatusCode = 200;
return YourObject;
}
[HttpPost]
public JsonResult ContactAdd(ContactViewModel contactViewModel)
{
if (ModelState.IsValid)
{
var job = new Job { Contact = new Contact() };
Mapper.Map(contactViewModel, job);
Mapper.Map(contactViewModel, job.Contact);
_db.Jobs.Add(job);
_db.SaveChanges();
//you do not even need this line of code,200 is the default for ASP.NET MVC as long as no exceptions were thrown
//Response.StatusCode = (int)HttpStatusCode.OK;
return Json(new { jobId = job.JobId });
}
else
{
Response.StatusCode = (int)HttpStatusCode.BadRequest;
return Json(new { jobId = -1 });
}
}
The way to do this in .NET Core is (at the time of writing) as follows:
public async Task<IActionResult> YourAction(YourModel model)
{
if (ModelState.IsValid)
{
return StatusCode(200);
}
return StatusCode(400);
}
The StatusCode method returns a type of StatusCodeResult which implements IActionResult and can thus be used as a return type of your action.
As a refactor, you could improve readability by using a cast of the HTTP status codes enum like:
return StatusCode((int)HttpStatusCode.OK);
Furthermore, you could also use some of the built in result types. For example:
return Ok(); // returns a 200
return BadRequest(ModelState); // returns a 400 with the ModelState as JSON
Ref. StatusCodeResult - https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.mvc.statuscoderesult?view=aspnetcore-2.1