Hi I'm new to umbraco MVC. I'm using version 7. What I'm trying to do is following:
An External page www.ble1.com is posting to my page www.le2.com/recieve when that happens ble1 is posting to the page and in the browser dev tools I can see the Form Data name of the parameter (tok) and some encoded string.
Now I want to take this data and send it to the controller code behind the macro running on my page www.le2.com/recieve. How would this be possible? I'm used to workin in asp.NET where I have the pageLoad function in code behind but I'm confused how to tackle this in Umbraco MVC.
What I have done so far is Create cshtml:
#inherits Umbraco.Web.Macros.PartialViewMacroPage
<script type="text/javascript">
$(document).ready(function () {
$.ajax({
type: "POST",
contentType: "application/json; charset=utf-8",
url: '../../../umbraco/surface/land/Login',
data: JSON.stringify({}),
dataType: 'json',
success: function (data) {
alert(data);
},
error: function (data) {
alert(data.d);
}
});
});
</script>
My Controller
public JsonResult Login()
{
//Don't know what to do here!!!!
//Everything that I have tryed has failed. Calling Request....etc.
}
I have never worked with Umbraco, but I have with MVC.
You Login method is not marked to receive POST requests. You need to use the attribute [HttpPost]
Your Login method does not have any Arguments, so, even if you fix your issue #1, it will not get any data.
So, first, you need some data in your Action Method, so you either need a ViewModel or a set or parameters, this is a ViewModel sample:
public class MyLoginViewModel
{
public string UserName { get; set; }
public string Password { get; set; }
}
Now we use that ViewModel in the Action Method:
[HttpPost]
public JsonResult Login(MyLoginViewModel model)
{
if (ModelState.IsValid)
{
// Do something here (probably use Umbraco internal's authorization layer)
var valid = (model.UserName == "user" && model.Password == "pwd");
if (valid)
return Json(new { code = 0, message = "OK" });
else
return Json(new { code = 10, message = "User/Password does not match" });
}
// Model is invalid, report error
return Json(new { code = -1, message = "invalid arguments" });
}
It is a very naive example, it makes sure the ViewModel is Valid, if it is, it performs the actual login logic, in this sample is just checks 2 values and returns the status.
In the HTML page, you could have:
<input type="text" id="userName" />
<input type="text" id="password" />
<button id="login">Login</button>
<script>
$(document).ready(function () {
$("#login").click(function () {
$.ajax({
type: "POST",
contentType: "application/json; charset=utf-8",
url: '/home/Login',
data: JSON.stringify({ UserName: $('#userName').val(), Password: $('#password').val() }),
dataType: 'json',
success: function (data) {
alert(data.message);
},
error: function (data) {
alert("An error has occurred while processing your request");
}
});
})
});
</script>
Again, very a naive example.
I hope it gives you enough information to adapt it to Umbraco.
Sorry I cannot give you Umbraco specific information.
Related
Not for the first time, I'm seeing that my Razor Pages seem to be handling GET/POST actions strangely when posting with ajax.
The latest example looks like this:
#inject IAntiforgery antiForgery
#{
ViewData["Title"] = "Disclaimers";
Layout = "~/Pages/Shared/_Blade.cshtml";
var token = antiForgery.GetAndStoreTokens(HttpContext).RequestToken;
}
$(".save-button").on("click", function(e) {
e.preventDefault;
const body = document.querySelector(".editor").innerText;
let disclaimer = {
clientid: parseInt($("#Disclaimer_Client_Id").val()),
description: $("#Disclaimer_Description").val(),
type: $("#Disclaimer_Type").val(),
markup: body
};
$.ajax({
method: "GET",
url: "./Create?handler=Create",
headers: {
"RequestValidationToken": "#token"
},
data: disclaimer,
dataType: "application/json",
success: function (data) {
console.log(data);
},
error: function (data) {
console.log(data);
}
});
});
I've done it this way because I'm using quilljs which employs a div for it's rich text editor. I can't use asp-for bindings on the div to bind it to the model.
public async Task<IActionResult> OnGetCreate(CreateDisclaimerViewmodel model)
{
var disclaimer = new Disclaimer
{
Created = DateTime.Now,
CreatedBy = User.Identity.Name,
Description = model.Description,
Markup = model.Markup,
Type = model.Type
};
if (model.ClientId > 0)
{
disclaimer.Client = await context.Clients.FindAsync(model.ClientId);
}
context.Disclaimers.Add(disclaimer);
await context.SaveChangesAsync();
return Redirect("/Disclaimers/Index");
}
With the code set up as using a GET method, it all works, but in this case, it should clearly be a POST.
Change it to a POST however and an empty response is returned with HTTP 400...
$(".save-button").on("click", function(e) {
e.preventDefault;
const body = document.querySelector(".editor").innerText;
let disclaimer = {
clientid: parseInt($("#Disclaimer_Client_Id").val()),
description: $("#Disclaimer_Description").val(),
type: $("#Disclaimer_Type").val(),
markup: body
};
$.ajax({
// Only the method changes here, everything else is above.
method: "POST",
url: "./Create?handler=Create",
headers: {
"RequestValidationToken": "#token"
},
data: disclaimer,
dataType: "application/json",
success: function (data) {
console.log(data);
},
error: function (data) {
console.log(data);
}
});
});
And the page model:
// Only the method changes (OnGetCreate becomes OnPostCreate).
public async Task<IActionResult> OnPostCreate(CreateDisclaimerViewmodel model)
{
var disclaimer = new Disclaimer
{
Created = DateTime.Now,
CreatedBy = User.Identity.Name,
Description = model.Description,
Markup = model.Markup,
Type = model.Type
};
if (model.ClientId > 0)
{
disclaimer.Client = await context.Clients.FindAsync(model.ClientId);
}
context.Disclaimers.Add(disclaimer);
await context.SaveChangesAsync();
return Redirect("/Disclaimers/Index");
}
This clearly should be a POST request but it simply won't work when using POST.
So what am I missing or misunderstanding? And since the solution can't be to use GET, what's the solution?
Shorten answer:
You use the wrong header name, it should be RequestVerificationToken:
headers: {
"RequestVerificationToken": "#token"
},
You are getting a 400 (Bad Request) response because the framework expects the RequestVerificationToken as part of the posted request. Be sure you have send it correctly.
Common way use ajax post in Razor Pages
Be sure your form tag does not have action attribute and then it will dynamically add a hidden input for token (You can F12 in browser to check whether your html contains input named __RequestVerificationToken, Ctrl+F and search for __RequestVerificationToken):
<form method="post">
//other elements...
<input class="save-button" type="button" value="CHANGE"/>
</form>
#section Scripts
{
<script>
$(".save-button").on("click", function(e) {
e.preventDefault;
//...
$.ajax({
// Only the method changes here, everything else is above.
method: "POST",
url: "?handler=Location",
headers: {
RequestVerificationToken: $('input:hidden[name="__RequestVerificationToken"]').val()
},
data: disclaimer,
dataType: "application/json",
//...
});
});
</script>
}
Otherwise, you will need manually add it by using #Html.AntiForgeryToken() in the form:
<form method="post">
//other elements...
#Html.AntiForgeryToken()
<input class="save-button" type="button" value="CHANGE"/>
</form>
I'm wondering how to display a succes or error message on succes or fail by a controller action in my MVC project with bootstrap. For example I got the following action:
Input:
Javascript method to send data to controller:
//Sends data filled in in modal to backend.
$(document).ready(function () {
$("#btnSubmit").click(function () {
var datastring = $("#myForm").serialize();
$.ajax({
type: "POST",
url: "/ApiBroker/AddApi",
dataType: 'json',
data: datastring,
});
$('#myModal').modal('hide');
$('body').removeClass('modal-open');
$('.modal-backdrop').remove();
})
})
Controller method:
[HttpPost]
public ActionResult AddApi(ApiRedirect model)
{
var data = model;
try
{
List<ApiRedirect> list = dbProducts.ApiRedirects.ToList();
int companyID = dbProducts.Companies.Where(x => x.CompanyName == model.Company.CompanyName).FirstOrDefault().CompanyID;
int mappingID = dbProducts.MappingNames.Where(x => x.Name == model.MappingName.Name).FirstOrDefault().MappingID;
ApiRedirect api = new ApiRedirect();
api.ApiName = model.ApiName;
api.CompanyID = companyID;
api.ApiURL2 = model.ApiURL2;
api.MappingID = mappingID;
api.ResponseType = model.ResponseType;
dbProducts.ApiRedirects.Add(api);
dbProducts.SaveChanges();
return View ();
}
catch (Exception ex){
throw ex;
}
}
If the method AddUser added the user into my database I want to display a error message, and if the user was not added I want to display a error message. I dont know how to achieve this, any suggetions?
Thanks in advance!
UPDATE
So the alert works but the POST call is getting the following internal server error:
Firstly you ajax needs to be updated to use a success or failure
$.ajax({
type: 'POST',
url: "/ApiBroker/AddApi",
data: datastring,
dataType: 'json',
success:
function(data){
//... put your logic here
},
error:
function(){ alert('error'); }
});
Secondly you need to update your controller action to return a IHttpActionResult where you can specify a Response message.
If you look at this
HttpResponseMessage
I am realy struggling with this and would apprecate any advice.
I have this field
<input id="scanInput" type="text" placeholder="SCAN" class="form-control" />
For which I would like to make an ajax call when the field changes, so I tried
<script>
$("#scanInput").change(function () {
console.log('ye');
$.getJSON("?handler=GetPartDetails", function (data) {
//Do something with the data.
console.log('yay?');
}).fail(function (jqxhr, textStatus, error) {
var err = textStatus + ", " + error;
console.log("Request Failed: " + err);
});
});
</script>
Where my PageModel has this method
[HttpPost]
public IActionResult GetPartDetails()
{
return new JsonResult("hello");
}
and the url for the page in question is /packing/package/{id}
Now when I change the input value, I see ye on the console, and I can see that the network called http://localhost:7601/Packing/Package/40?handler=GetPartDetails (the correct URL I think?) with status code 200
But My breakpoint in GetPartDetails never hits, and I don't see yay? in the console.
I also see this message from the fail handler:
Request Failed: parsererror, SyntaxError: JSON.parse: unexpected character at line 3 column 1 of the JSON data
But I'm not even passing any JSON data... why must it do this
I also tried this way :
$.ajax({
type: "POST",
url: "?handler=GetPartDetails",
contentType : "application/json",
dataType: "json"
})
but I get
XML Parsing Error: no element found
Location: http://localhost:7601/Packing/Package/40?handler=GetPartDetails
Line Number 1, Column 1:
I also tried
$.ajax({
url: '/?handler=Filter',
data: {
data: "input"
},
error: function (ts) { alert(ts.responseText) }
})
.done(function (result) {
console.log('done')
}).fail(function (data) {
console.log('fail')
});
with Action
public JsonResult OnGetFilter(string data)
{
return new JsonResult("result");
}
but here I see the result text in the console but my breakpoint never hits the action and there are no network errors..............
What am I doing wrong?
Excuse me for posting this answer, I'd rather do this in the comment section, but I don't have the privilege yet.
Shouldn't your PageModel look like this ?
[HttpPost]
public IActionResult GetPartDetails() {
return new JsonResult {
Text = "text", Value = "value"
};
}
Somehow I found a setup that works but I have no idea why..
PageModel
[HttpGet]
public IActionResult OnGetPart(string input)
{
var bellNumber = input.Split('_')[1];
var partDetail = _context.Parts.FirstOrDefault(p => p.BellNumber == bellNumber);
return new JsonResult(partDetail);
}
Razor Page
$.ajax({
type: 'GET',
url: "/Packing/Package/" + #Model.Package.Id,
contentType: "application/json; charset=utf-8",
dataType: "json",
data: {
input: barcode,
handler: 'Part'
},
success: function (datas) {
console.log('success');
$('#partDescription').html(datas.description);
}
});
For this issue, it is related with the Razor page handler. For default handler routing.
Handler methods for HTTP verbs ("unnamed" handler methods) follow a
convention: On[Async] (appending Async is optional but
recommended for async methods).
For your original post, to make it work with steps below:
Change GetPartDetails to OnGetPartDetails which handler is PartDetails and http verb is Get.
Remove [HttpPost] which already define the Get verb by OnGet.
Client Request
#section Scripts{
<script type="text/javascript">
$(document).ready(function(){
$("#scanInput").change(function () {
console.log('ye');
$.getJSON("?handler=PartDetails", function (data) {
//Do something with the data.
console.log('yay?');
}).fail(function (jqxhr, textStatus, error) {
var err = textStatus + ", " + error;
console.log("Request Failed: " + err);
});
});
});
</script>
}
You also could custom above rule by follow the above link to replace the default page app model provider
I am trying as the title says to return a Json message from the Controller to the View after it validates.
I have made a breakpoint, and I know that the code works from Controller side, and that my JavaScript calls with success the ActionResult now. How do I display that message in the View?
There are two buttons, stamp in and stamp out. If the user stamps in twice, it should get a message, same with stamp out. I have two ActionResults who are indentical except some message and string changes.
Controller:
[HttpPost]
public ActionResult CreateStamp(Stamping stampingmodel)
{
var validateMsg = "";
stampingmodel.Timestamp = DateTime.Now;
stampingmodel.StampingType = "in";
if (stampingmodel.User == null || ModelState.IsValid)
{
var idValidated = db.Users.Find(model.UserId);
if (idValidated != null)
{
var stamp =
db.Stampings.Where(s => s.UserId == stampingmodel.UserId)
.OrderByDescending(s => s.Timestamp)
.FirstOrDefault();
if (stamp.StampingType == stampingmodel.StampingType)
{
if (stampingmodel.StampingType == "in")
{
validateMsg = "Stamped Twice In A Row!";
}
}
else
{
if (stampingmodel.StampingType == "in")
{
validateMsg = "Stamped In, Welcome.";
}
}
}
db.Stampings.Add(stampingmodel);
db.SaveChanges();
}
return Json(new {Message = validateMsg });
JavaScript:
$(document).ready(function () {
$("#stampInBtn").click(function () {
var userId = $("#userId").val();
$.ajax({
url: "ComeAndGo/CreateStamp",
type: "POST",
dataType: "json",
data: {
userId: userId,
}
});
});
View:
<input type="text" id="idUser" class="form-control" />
<br />
<input type="submit" value="IN" id="stampInBtn" />
I have more code inside the View of course; divs, head, body, title and scripts. But it's perhaps a little irrelevant.
What should I do to successfully show those messages?
Regards.
Add a success function to the ajax call
$.ajax({
url: "ComeAndGo/CreateStamp",
type: "POST",
dataType: "json",
data: { userId: userId },
success: function(data) {
// data contains the value returned by the server
console.log(data);
}
});
So if the controller returns
return Json("This is a message");
the value of data will be "This is a message". Note the return value can be a complex type or a partial view
You are getting the value of $("#userId"), but your input has an id of idUser.
Try making your input:
<input type="text" id="userId" class="form-control" />
Also it would be a good idea to provide your Stamping model structure as it seems that you only pass the user id in your post and nothing else.
Change your javascript code as following:
$(document).ready(function () {
$("#stampInBtn").click(function () {
var userId = $("#userId").val();
$.ajax({
url: "ComeAndGo/CreateStamp",
type: "POST",
dataType: "json",
data: {
userId: userId,
},
success: function(data) {
var objData= jQuery.parseJSON(data);
alert(objData.Message );
},
error: function (request, status, error) {
alert(request.responseText);
}
});
});
});
I have the Controller method below made in ASP.NET MVC 3 (C#) who returns a PartialView:
public ActionResult InsertEmail(long idPerson)
{
PersonEmailViewModel mail = new PersonEmailViewModel();
mail.email.Person_idPerson = idPerson;
return PartialView(mail);
}
The method that I need to execute on submit form is:
[HttpPost]
public ActionResult InsertNewEmail(PersonEmail mail)
{
mail.idPersonEmail = mail.Insert(mail);
return Json(mail);
}
My partialView contains this code:
#model PlatformLib_MySql.BLL.Person.PersonEmailViewModel
<form action="" id="frmNewEmail" method="post">
<div>
E-mail: #(Html.TextBoxFor(m => m.email.email))
#(Html.HiddenFor(m => m.email.Person_idPerson))
<input type="submit" value="Insert" id="btnSubmitMailInsert" />
<input type="button" value="Cancel" id="btnCancelMailInsert" />
</div>
</form>
In my JS file I run this code on #btnSubmitMailInsert button:
jQuery("#btnSubmitMailInsert").click(function () {
submitNewEmail();
window.location.reload();
});
function submitNewEmail() {
event.preventDefault();
var mail = {
email: jQuery("#frmNewEmail #email_email").val(),
Person_idPerson: jQuery("#frmNewEmail #email_Person_idPerson").val()
};
var request = jQuery.ajax({
url: '/Person/InsertNewEmail',
data: mail,
type: 'POST',
dataType: 'json',
cache: false
});
request.done(function (msg) {
console.log(msg);
});
request.fail(function (msg) {
console.log(msg);
});
}
My problem is focused on Ajax request. Rarely I can make the "happy way", where on submit click, the event is activated on jQuery, calls the method "submitNewEmail()", that calls an Ajax, executes the method on controller and pass with success. But not so... It always returns with fail, not because error returned by controller method, but simply because ajax doesn't runs properly, doesn't execute the method on controller, even with a breakpoint inserted there (on VS2010).
In this JS code posted by me here is an attempt to alternatively solve this problem, unsuccessful.
The original code is:
jQuery.ajax({
url: '/Person/InsertNewEmail',
data: mail,
type: 'POST',
dataType: 'json',
cache: false,
success: function (result) {
debugger;
jQuery("#tblEmail").append("<tr><td>Email inserido</td></tr>");
},
error: function () {
debugger;
alert("Erro ao inserir e-mail.");
}
});
I left the "console.log(msg)" temporary, just to solve this problem.
Can someone of you tell me what is happening, or to point where is my error?
I found the problem. Everything was right, but some detail damaged the code: window.location.reload();
I made some changes in my code, that looks like it:
jQuery.ajax({
url: '/Person/InsertNewEmail',
data: mail,
type: 'POST',
dataType: 'json',
cache: false
}).done(function (data) {
// Do something
});
The another way is right too, the only relevant change was:
jQuery("#btnSubmitMailInsert").click(function () {
event.preventDefault();
submitNewEmail();
// window.location.reload // -> Commented for testing and everything worked fine.
});
Thanks for trying to help me. This helped me so much.