I have a MVC Controller with the following signature:-
[HttpPost]
public async Task<JsonResult> SaveBrochureAsAttachment(Guid listingId, HttpPostedFileWrapper attachmentFile)
{
///some logic
}
How do I make an ajax call and send the file attachment and additional listingId parameter. Currently I am only able to send the attachment like this:-
var uploadFile = function () {
if ($('#attachmentFile').val()) {
}
else {
alert('No File Uploaded');
return;
}
var formData = new FormData($('#uploadForm')[0]);
$.ajax({
url: '/Listing/SaveBrochureAsAttachment',
type: 'POST',
data: formData,
async: false,
success: function (data) {
alert('File Uploaded');
},
error: function (jqXHR, textStatus, errorThrown) {
$("#FileUpload").replaceWith($("#FileUpload").val('').clone(true));
alert('File Uploaded Error');
},
cache: false,
contentType: false,
processData: false
});
return false;
}
Currently as you folks can see I am only able to send the attachment. How do I also send the Guid listingId to match the controller signature.
Try adding another formdata parameter:
formData.append("listingId", guidValue);
Provided you have the guid value accessible. You can use this to generate one from the client. Or create one from the server:
var guidValue = '#Guid.NewGuid()';
one approach would be to your controller accept viewmodel (a class) which contains different property you need. and use formdata.append required stuff to post to the server.
On Server side; you will need to use modelbinder so that you will get required stuff populated.
Refernce for modelbinder : https://www.dotnetcurry.com/aspnet-mvc/1261/custom-model-binder-aspnet-mvc
you can get more on google. :)
Related
I need a way to generate a new unique id for a user when a person focuses out of a textbox. I am using MVC 5 for this application. Here is my controller, everything in the controller has been unit tested and it does return the string value that I need.
Controller. I was able to visit that URL, and I did download a JSON file with the correct data.
public ActionResult GetNewId()
{
string newId = utils.newEmployeeId();
return Json(new {eId = newId}, JsonRequestBehavior.AllowGet);
}
Javascript, JQuery call to that controller. I do not know how to properly reference the ActionResult. I keep getting undefined errors on eId.
$(function () {
$('#employeeId').focusout(function () {
if($("#employeeId").val() === "NP")
$.ajax({
type: 'GET',
url: '#Html.ActionLink("GetNewId", "Employees")',
data: { 'eId': eId },
dataType: 'json',
success: function (response) {
$("#employeeId").val(eId);
},
error: function (response) {
alert(response);
}
});
});
});
The problem is with yout ajax request:
1.you need to change the url in the reuqest but it like this
{{yourcontroller}/GetNewId}
2.remove the "data: { 'eId': eId }" you dont need it, youre not posting anything to the server.
change your $("#employeeId").val(eId); to
$("#employeeId").val(response.eId);
this will 100% work
The following javascript code works with the facebook login window appearing and allowing a user to login. The response values are captured and I know it works as alerts appear where setup but I cannot pass the value back to a controller method.
#RequestMapping(value ="/getAccessToken" , method = RequestMethod.POST)
public #ResponseBody String getAccessToken(#RequestBody String token){
System.out.println(token);
return token;
}
Javascript method called:
function doLogin() {
FB.login(function(response) {
alert(response);
console.log(response);
if (response.authResponse) {
alert(response.authResponse.userID);
alert(response.authResponse.accessToken);
var Token = response.authResponse.accessToken;
alert(Token);
$.ajax({
type: "POST",
url: "/HelloController/getAccessToken",
data: Token,
success: function (result) {
alert("Token");
},
error: function (result) {
alert("oops");
}
});
document.getElementById('loginBtn').style.
display = 'none';
getUserData();
}}, {perms:'manage_pages',
scope: 'email,public_profile', return_scopes: true});
};
The error I get is the following:
WARN 25660 --- [nio-8080-exec-9]
o.s.web.servlet.PageNotFound :
Request method 'POST' not supported
Appreciate responses.
The problem could be that you are using a new version of JQuery that sends request data as post form data instead of JSON as default. Try changing your ajax call to the following. The form data would not be recognized by your controller so if this is the case you should see a 404.
$.ajax({
type: "POST",
traditional: true,
url: "/HelloController/getAccessToken",
data: JSON.stringify(Token),
success: function (result) {
alert("Token");
},
error: function (result) {
alert("oops");
}
});
For reference see this post: Send JSON data via POST (ajax) and receive json response from Controller (MVC)
I wrote a JQuery script to do a user login POST (tried to do what I have done with C# in the additional information section, see below).
After firing a POST with the JQuery code from my html page, I found the following problems:
1 - I debugged into the server side code, and I know that the POST is received by the server (in ValidateClientAuthentication() function, but not in GrantResourceOwnerCredentials() function).
2 - Also, on the server side, I could not find any sign of the username and password, that should have been posted with postdata. Whereas, with the user-side C# code, when I debugged into the server-side C# code, I could see those values in the context variable. I think, this is the whole source of problems.
3 - The JQuery code calls function getFail().
? - I would like to know, what is this JQuery code doing differently than the C# user side code below, and how do I fix it, so they do the same job?
(My guess: is that JSON.stringify and FormURLEncodedContent do something different)
JQuery/Javascript code:
function logIn() {
var postdata = JSON.stringify(
{
"username": document.getElementById("username").value,
"password": document.getElementById("password").value
});
try {
jQuery.ajax({
type: "POST",
url: "http://localhost:8080/Token",
cache: false,
data: postdata,
dataType: "json",
success: getSuccess,
error: getFail
});
} catch (e) {
alert('Error in logIn');
alert(e);
}
function getSuccess(data, textStatus, jqXHR) {
alert('getSuccess in logIn');
alert(data.Response);
};
function getFail(jqXHR, textStatus, errorThrown) {
alert('getFail in logIn');
alert(jqXHR.status); // prints 0
alert(textStatus); // prints error
alert(errorThrown); // prints empty
};
};
Server-side handling POST (C#):
public override async Task ValidateClientAuthentication(
OAuthValidateClientAuthenticationContext context)
{
// after this line, GrantResourceOwnerCredentials should be called, but it is not.
await Task.FromResult(context.Validated());
}
public override async Task GrantResourceOwnerCredentials(
OAuthGrantResourceOwnerCredentialsContext context)
{
var manager = context.OwinContext.GetUserManager<ApplicationUserManager>();
var user = await manager.FindAsync(context.UserName, context.Password);
if (user == null)
{
context.SetError(
"invalid_grant", "The user name or password is incorrect.");
context.Rejected();
return;
}
// Add claims associated with this user to the ClaimsIdentity object:
var identity = new ClaimsIdentity(context.Options.AuthenticationType);
foreach (var userClaim in user.Claims)
{
identity.AddClaim(new Claim(userClaim.ClaimType, userClaim.ClaimValue));
}
context.Validated(identity);
}
Additional information: In a C# client-side test application for my C# Owin web server, I have the following code to do the POST (works correctly):
User-side POST (C#):
//...
HttpResponseMessage response;
var pairs = new List<KeyValuePair<string, string>>
{
new KeyValuePair<string, string>( "grant_type", "password"),
new KeyValuePair<string, string>( "username", userName ),
new KeyValuePair<string, string> ( "password", password )
};
var content = new FormUrlEncodedContent(pairs);
using (var client = new HttpClient())
{
var tokenEndpoint = new Uri(new Uri(_hostUri), "Token"); //_hostUri = http://localhost:8080/Token
response = await client.PostAsync(tokenEndpoint, content);
}
//...
Unfortunately, dataType controls what jQuery expects the returned data to be, not what data is. To set the content type of the request data (data), you use contentType: "json" instead. (More in the documentation.)
var postdata = JSON.stringify(
{
"username": document.getElementById("username").value,
"password": document.getElementById("password").value
});
jQuery.ajax({
type: "POST",
url: "http://localhost:8080/Token",
cache: false,
data: postdata,
dataType: "json",
contentType: "json", // <=== Added
success: getSuccess,
error: getFail
});
If you weren't trying to send JSON, but instead wanted to send the usual URI-encoded form data, you wouldn't use JSON.stringify at all and would just give the object to jQuery's ajax directly; jQuery will then create the URI-encoded form.
try {
jQuery.ajax({
type: "POST",
url: "http://localhost:8080/Token",
cache: false,
data: {
"username": document.getElementById("username").value,
"password": document.getElementById("password").value
},
dataType: "json",
success: getSuccess,
error: getFail
});
// ...
To add to T.J.'s answer just a bit, another reason that sending JSON to the /token endpoint didn't work is simply that it does not support JSON.
Even if you set $.ajax's contentType option to application/json, like you would to send JSON data to MVC or Web API, /token won't accept that payload. It only supports form URLencoded pairs (e.g. username=dave&password=hunter2). $.ajax does that encoding for you automatically if you pass an object to its data option, like your postdata variable if it hadn't been JSON stringified.
Also, you must remember to include the grant_type=password parameter along with your request (as your PostAsync() code does). The /token endpoint will respond with an "invalid grant type" error otherwise, even if the username and password are actually correct.
You should use jquery's $.param to urlencode the data when sending the form data . AngularJs' $http method currently does not do this.
Like
var loginData = {
grant_type: 'password',
username: $scope.loginForm.email,
password: $scope.loginForm.password
};
$auth.submitLogin($.param(loginData))
.then(function (resp) {
alert("Login Success"); // handle success response
})
.catch(function (resp) {
alert("Login Failed"); // handle error response
});
Since angularjs 1.4 this is pretty trivial with the $httpParamSerializerJQLike:
.controller('myCtrl', function($http, $httpParamSerializerJQLike) {
$http({
method: 'POST',
url: baseUrl,
data: $httpParamSerializerJQLike({
"user":{
"email":"wahxxx#gmail.com",
"password":"123456"
}
}),
headers:
'Content-Type': 'application/x-www-form-urlencoded'
})
})
I'm trying to get all my posts from the database to be displayed with the help of ajax or getjson but can't get it to work. Using mvc web api and I have a view where I want to display it. There is a method working called post so nothing wrong with my routing etc.
Code for my views js-script, I want to display all posts with the help of my mvc api controller and ajax in a div called #userMessage.
$(document).ready(function() {
$('#btnGetPosts').click(function() {
jQuery.support.cors = true;
var recieverID = $('#RecieverID').val();
$.ajax({
url: "/api/Posts/GetPosts" ,
//data: (?)
type: "GET",
dataType: "jsonp",
error: function(request, status, error) {
alert(request.responseText);
},
success: function(data) {
alert(data);
}
});
});
});
my controller method to get all the posts
// GET: api/Posts
public IEnumerable<Post> GetPosts()
{
//querystring is made to get the recieverID, it's also reachable in the view. //("#RecieverID")
string querystring = HttpContext.Current.Request.QueryString["Username"];
// Converts Username querystring to a user-id
int id = UserRepository.GetUserId(querystring);
// uses linq to get a specific user post (all posts)
var userPost = PostRepository.GetSpecificUserPosts(id);
return userPost;
}
my PostRepository.GetSpecifiedUserPosts method in my repository
public List<Post> GetSpecificUserPosts(int user)
{
using (var context = new DejtingEntities())
{
var result = context.Posts
.Where(x => x.RecieverID == user)
.OrderByDescending(x => x.Date)
.ToList();
return result;
}
Try this
$(document).ready(function() {
$('#btnGetPosts').click(function() {
jQuery.support.cors = true;
var recieverID = $('#RecieverID').val();
$.ajax({
url: "/api/Posts/Posts" ,
data: {
username: recieverID
},
type: "GET",
dataType: "jsonp",
error: function(request, status, error) {
alert(request.responseText);
},
success: function(data) {
alert(data);
}
});
});
});
and in code behind,
public IEnumerable<Post> GetPosts(string username)
{
// Converts Username querystring to a user-id
int id = UserRepository.GetUserId(username);
// uses linq to get a specific user post (all posts)
var userPost = PostRepository.GetSpecificUserPosts(id);
return userPost;
}
You use wrong url. Try send ajax request to '/api/Posts'.
Also you can add routing attribute to the action [Route('/api/Posts/GetPosts')] and send request to '/api/Posts/GetPosts'.
See Calling the Web API with Javascript and jQuery and Routing in ASP.NET Web API.
I am aware this question has been answered before but I am somehow unable to hit an action within my controller.
Here is the Action
public JsonResult GetUpdate()
{
//get a list of valid elements
var result = getContent();
return Json(result, JsonRequestBehavior.AllowGet);
}
In my script:
$.ajax({
type: 'GET',
url: '#Url.Action("GetUpdate")',
dataType: 'json',
success: function (constraints) {
alert("Application updated");
},
error: function (ex) {
alert('Failed to retrieve update.' + ex);
}
});
Using fiddler I can hit GetUpdate but from the browser the Ajax call fails. Am I correctly accessing the URL?
Update:
The following is the error message:
"NetworkError: 404 Not Found - protocol://localhost:port/Controller/#Url.Action(%22GetUpdate%22)"
The following works through Fiddle:
protocol://localhost:port/Controller/GetUpdate
Razor code (C# and all other server-side script) is only executed from .cshtml files, therefore C# and Razor can't be used in .js files.
'#Url.Action("GetUpdate")' doesn't generate a URL, it's just a string, therefore you are trying to request protocol://domain:port/Controller#Url.Action("GetUpdate") which doesn't exist.
Here's what you can do:
In the .cshtml file you can store the generated URL in a JavaScript variable and pass it to the external JS file.
You can move your external JavaScript to the .cshtml file so you can use Razor.
use a relative string path like /Controller/GetUpdate
I would recommend the first one.
You can try this out,where _ApplicationPath is protocol://localhost:port/
$.ajax({
type: 'GET',
url: _ApplicationPath + "/ControllerName/GetUpdate",
dataType: 'json',
success: function (constraints) {
alert("Application updated");
},
error: function (ex) {
alert('Failed to retrieve update.' + ex);
}
});