I have an MVC5 application that has a method populates and returns a partial view. Since the method accepts an ID as a parameter, Id like to return an error if it is not supplied.
[HttpGet] public PartialViewResult GetMyData(int? id)
{
if (id == null || id == 0)
{
// I'd like to return an invalid code here, but this must be of type "PartialViewResult"
return new HttpStatusCodeResult(HttpStatusCode.BadRequest); // Does not compile
}
var response = MyService.GetMyData(id.Value);
var viewModel = Mapper.Map<MyData, MyDataViewModel>(response.Value);
return PartialView("~/Views/Data/_MyData.cshtml", viewModel);
}
What is the proper way to report an error for a method that returns a PartialViewResult as its output?
You could create a friendly error partial and do the following:
[HttpGet]
public PartialViewResult GetMyData(int? id)
{
if (id == null || id == 0)
{
// I'd like to return an invalid code here, but this must be of type "PartialViewResult"
return PartialView("_FriendlyError");
}
var response = MyService.GetMyData(id.Value);
var viewModel = Mapper.Map<MyData, MyDataViewModel>(response.Value);
return PartialView("~/Views/Data/_MyData.cshtml", viewModel);
}
This way there is a better user experience rather than just throwing them anything. You can customise that error partial to include some details that they did wrong etc.
You can use manual Exception
if (id == null || id == 0)
{
throw new Exception("id must have value");
}
if you work with ajax, you can handle error by error callback function
$.ajax({
type: 'POST',
url: '/yourUrl',
success: function (response) {
// call here when successfully // 200
},
error: function (e) {
// handle error in here
}
})
While you cannot return HttpStatusCodeResult as a PartialViewResult to set the response status code for you, you can certainly still do the manual labour yourself to achieve the same result.
Using the OP's example:
[HttpGet]
public PartialViewResult GetMyData(int? id)
{
if (id == null || id == 0)
{
// Return an invalid code here
HttpContext.Response.StatusCode = HttpStatusCode.BadRequest;
// Optionally set the description as well
HttpContext.Response.StatusDescription = "Bad Request";
// Return null as it doesn't matter anymore
return null;
}
var response = MyService.GetMyData(id.Value);
var viewModel = Mapper.Map<MyData, MyDataViewModel>(response.Value);
return PartialView("~/Views/Data/_MyData.cshtml", viewModel);
}
Success, by setting the status code directly on HttpContext.Response which is accessible from the base class Controller, and what HttpStatusCodeResult would've done anyway.
nJoy!
Related
I have a web-api, 2 tables in my SQL DB, JT and Sales. Before I add() to the database I need the poster to specify first in the uri whether he/she wants to post to JT table or Sales. My problem is that my post method only accepts one model binding, it doesn't want two like as shown on my code below. It doesn't have errors but when I post with that logic in mind it returns an error in POSTMAN that It can't bind multiple parameters ('JT' and 'Sales') to the request's content.
Here is my code:
[ResponseType(typeof(JT))]
public HttpResponseMessage PostJT(JT JT, Sales Sales, [FromUri] string tran)
{
try
{
if (ModelState.IsValid)
{
if (tran == null)
{
return Request.CreateResponse(HttpStatusCode.Unauthorized, "Unauthorized Access!");
}
else
{
switch (tran)
{
case "JT": db.JTs.Add(JT);
break;
case "sales": db.Sales_.Add(Sales);
break;
}
}
db.SaveChanges();
return Request.CreateErrorResponse(HttpStatusCode.OK, "Added!");
}
//below are just elses with return messages.
There is no direct way to pass multiple parameter but you can use the below work around
This link gives complete details on Web API passing Multiple parameter
$.ajax(
{
url: "samples/PostAlbum",
type: "POST",
contentType: "application/json",
data: JSON.stringify({ JT: jt, Sales: sales, UserToken: userToken }),
success: function (result) {
alert(result);
}
});
[HttpPost]
public string PostAlbum(JObject jsonData)
{
try
{
if (ModelState.IsValid)
{
if (tran == null)
{
return Request.CreateResponse(HttpStatusCode.Unauthorized,
"Unauthorized Access!");
}
else
{
dynamic json = jsonData;
JObject jtObject = json.JT;
JObject salesObject = json.Sales;
var jt = jtObject.ToObject<JT>();
var sales = salesObject.ToObject<Sales>();
if (jt != null)
{
db.JTs.Add(JT);
}
else if (sales != null)
{
db.Sales_.Add(Sales);
}
}
db.SaveChanges();
return Request.CreateErrorResponse(HttpStatusCode.OK, "Added!");
}
//below are just elses with return messages.
}
I want to do cusotm validation and return false and show message in case of validation fail.
In controller below code is used to submit posted data to database.
[HttpPost]
public JsonResult SubmitDa(IList<AdViewModel> s, String section)
{
...........
..........
ModelState.AddModelError("MessageError", "Please enter AttendanceDate");
JSONSubmit r = new JSONSubmit();
r.ErrorCount = iError;
r.errors = errors;
return Json(r, JsonRequestBehavior.AllowGet);
}
Below is the code in view file (cshtml)
#Html.ValidationMessage("MessageError")
.....
$.AJAX call to `SubmitDa` controller's method.
Message is not appearing at "MessageError" validation message. please suggest me what is wrong here.
Thanks
If you want to use the modelstate for errors you shouldn't really be sending a JSON response. Having said that you can handle it by having the controller return JSON only in the case of success, and the page handles the response differently
IE:
[HttpPost]
public ActionResult SubmitDa(IList<AdViewModel> s, String section)
{
...........
..........
ModelState.AddModelError("MessageError", "Please enter AttendanceDate");
JSONSubmit r = new JSONSubmit();
r.ErrorCount = iError;
r.errors = errors;
if (r.ErrorCount != 0)
return Json(r, JsonRequestBehavior.AllowGet);
return View("ViewName", s); // <-- just return the model again to the view,
// complete with modelstate!
}
on the page something like:
<script>
$("#buttonId").click({
$.ajax({
type: "POST",
url: "PostBackURL",
data: $("#formID").serialize(),
success: function (response){
//test for a property in the JSON response
if(response.ErrorCount && response.ErrorCount == 0)
{
//success! do whatever else you want with the response
} else {
//fail - replace the HTML with the returned response HTML.
var newDoc = document.open("text/html", "replace");
newDoc.write(response);
newDoc.close();
}
}
});
});
</script>
How to use $.post or $.getJSON to get json from mvc controlller but not working below? Would you like help me?
var controlRole = function () {
var _url = 'IsStudent/';
console.log('IsStudent');
$.post(_url, {}, function (data) {
console.log('IsStudent2');
if (data == "true") {
$('#btnSent_').hide();
$('#btnDraft_').hide();
$('#btn_Inbox_').show();
$('#btnTrash_').show();
$.post('FillProgramListByUser/', {}, function (result) {
console.log('IsStudent3');
console.log(result);
$("#liProgramContainer ul").append('<li ><a class="btn" href="javascript:;" data-title="Sent">'+result.Name+'</a><b></b></li>');
});
// $.getJSON("FillProgramListByUser/", user, updateFields);
}
else {
$('#btnSent_').show();
$('#btnDraft_').show();
$('#btn_Inbox_').show();
$('#btnTrash_').show();
}
});
}
Controller side:
public JsonResult FillProgramListByUser()
{
string UserName = SessionVariables.CurrentUser.UserName;
int OrganizationId = SessionVariables.CurrentUser.OrganizationId;
IList<Program> programs = new List<Program>();
if (UserName != "system_admin")
{
programs = Uow.Programs.GetAll().Where(q => q.OrganizationId == OrganizationId).ToList();
}
return Json(programs, "application/json", Encoding.UTF8, JsonRequestBehavior.AllowGet);
}
[HttpPost]
public string IsStudent()
{
string UserName = SessionVariables.CurrentUser.UserName;
if (UserName != "system_admin")
{
return "true";
}
else
{
return "false";
}
}
Your controller action should return a JsonResult and not some strings:
[HttpPost]
public ActionResult IsStudent()
{
string UserName = SessionVariables.CurrentUser.UserName;
if (UserName != "system_admin")
{
return Json(new { success = true });
}
return Json(new { success = false });
}
Also in your FillProgramListByUser action you don't need to be explicitly setting the content type response header nor the encoding:
public ActionResult FillProgramListByUser()
{
string UserName = SessionVariables.CurrentUser.UserName;
int OrganizationId = SessionVariables.CurrentUser.OrganizationId;
IList<Program> programs = new List<Program>();
if (UserName != "system_admin")
{
programs = Uow.Programs.GetAll().Where(q => q.OrganizationId == OrganizationId).ToList();
}
return Json(programs, JsonRequestBehavior.AllowGet);
}
Also adapt your script so that the urls are not hardcoded as in your example but you used URL helpers to generate them:
<script type="text/javascript">
var controlRole = function () {
var isStudentUrl = '#Url.Action("IsStudent")';
$.post(isStudentUrl, function (data) {
if (data.success) {
$('#btnSent_').hide();
$('#btnDraft_').hide();
$('#btn_Inbox_').show();
$('#btnTrash_').show();
var fillProgramListByUserUrl = '#Url.Action("FillProgramListByUser")';
$.post(fillProgramListByUserUrl, function (result) {
$("#liProgramContainer ul").append('<li><a class="btn" href="javascript:;" data-title="Sent">'+result.Name+'</a><b></b></li>');
});
} else {
$('#btnSent_').show();
$('#btnDraft_').show();
$('#btn_Inbox_').show();
$('#btnTrash_').show();
}
});
};
</script>
Next put breakpoints in your controller actions and see if they are hit. Also don't forget to look at the network tab of your javascript debugging tool (FireBug or Chrome Developer Toolbar) which is where you will see the exact AJAX request being sent to the server and what does the server respond to. You will see the HTTP status code returned and you could also see the contents of the response. If the status code is non 2xx the success callback of your AJAX request will not be executed.
Another thing you should check is the Program model which is being returned by your FillProgramListByUser controller action. In there you are attempting to JSON serialize an IList<Program> but be careful: if this Program class has some circular references (often happens if you don't use view models but are directly passing your EF domain models to the views) you won't be able to JSON serialize it. The answer is of course obvious: use a view model.
I am new to asp and I would like to ask you for some help. I built store with MvcMusicStore tutorial help.Now I want to search in the database by using OrderId.As soon as the orderid is and if we click on the submit button it should display the corresponding rows from the database. My method is as follows
public ActionResult SearchOrder(int? myid)
{
var s = from sp in db.Railways
select sp;
string oid = myid.ToString();
if (!string.IsNullOrEmpty(oid))
{
s = s.Where(st => st.OrderID == (Convert.ToInt16(oid)));
}
return View(s.ToList());
}
Also i tired with the code as
public ActionResult SearchOrder(int? myid)
{
if (id != null)
{
if (ViewBag.OrderID == id.Value)
{
s = s.Where(st => st.OrderID == id);
}
}
return View(s);
}
In the second method when i tried it is neither displaying the contents nor showing the error.
Pls do help me.
Try this:
public ActionResult SearchOrder(int? myid)
{
var s = from sp in db.Railways
select sp;
if (myid.HasValue)
{
s = s.Where(st => st.OrderID == myid.Value);
}
return View(s.ToArray());
}
First your example will not work because string oid = myid.ToString(); will not be null or empty string if myid is null; Second example will fail (ViewBag.OrderID == id.Value) condition and moreover will not compile.
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