I am looking to send information from a form submitted on a webpage to be processed by the WebAPI of another website. The form is basically a series of fields as follows:
Account Type (radio button 2 options)
Name
Email
Phone Number
Tariff (dropdown 4 options)
On the Web API controller end I have created a class called QuickSwitch which is coded as follows:
public class QuickSwitch
{
[StringLength(20)]
public string AccountType { get; set; }
[StringLength(50)]
public string FullName { get; set; }
[StringLength(100)]
public string Email { get; set; }
[StringLength(15)]
public string PhoneNumber { get; set; }
public string Tariff { get; set; }
}
On the WebAPI controller I have the following method:
[HttpPost]
public HttpResponseMessage PostMXBData([FromBody] QuickSwitch qs)
{
#region Customer Details
var accountType = "";
var name = "";
var email = "";
var phoneNumber = "";
var mobileNumber = "";
var houseNumber = "";
var address = "";
var town = "";
var postcode = "";
var county = "";
var keypadAccountNumber = "";
var keypadTariff = "";
var billpayCustomerNumber = "";
var mprnNumber = "";
var billpayTariff = "";
#endregion
}
How can I POST the data on the webpage so that it links the fields from the form to the QuickSwitch class on the WebAPI controller end. I was then hoping to be able to sign variables as:
var accountType = qs.AccountType;
You can use a simple Ajax post with JQuery.
var data = {
fullName: 'john',
email: 'a#c.com',
// etc.etc.
};
$.ajax({
type: "POST",
url: 'http://localhost/api/mycontroller/PostMXBData',
data: data, // your QuickSwitch object
success: successCallbackFunction
});
function successCallbackFunction(result){
// ok!
}
There is one big flaw with your approach on posting data using a simple form to a WebAPI endpoint: what happens after the data is posted?
If you simply create a form and POST data to your controller then your web browser will show you the response from the server, and if it is a Web API endpoint it will show you not a page but (usually) a JSON/XML response (or an empty response if you simply return a 200 status code in your controller). This is not what you want (I believe).
You have two options then:
POST your form to a page in the same website, and then make a server-side request to the Web API endpoint (this depends on the technology used for your web page e.g. MVC, ASP.NET Web Pages, etc.);
Use AJAX and send your data to the Web API endpoint in background.
For the second option, assuming you are using jQuery:
$('#mySubmitButton').click(function (e) {
e.preventDefault();
var postData = {
accountType: $('#accountTypeInput').val(),
//etc...
}
$.ajax({
type: "POST",
dataType: "json",
url: "http://myhost/api/MyApi",
data: postData ,
success: function (data) {
alert(data);
},
error: function (error) {
alert('error!');
}
});
});
In the success callback you may want to redirect the user to a form submitted page, or simply show a success message in the page (it's up to you).
Related
I am trying to add a contact email address to a existing campaign list named- "liakat". But I am getting a response from getresponse.com saying httpStatus 400, which you can check on the attached pitures. I have added a temporary api key, so you can test it yourself too. I am following this document from getresponse.com. Anyone who can fix this issue?
Controller:
string email = "test#gmail.com";
// Test Campaign name - "pikaa"
// "pikaa" named campaign ID->ee104303
// our api key-> 948dsdfsdfs1a017a07f3c6
var client = new RestClient("https://api.getresponse.com/v3/contacts");
var request = new RestRequest(Method.POST);
request.RequestFormat = DataFormat.Json;
var root = new RootObject();
root.campaign = new Campaign();
root.name = "Mr Men";
root.email = "test#gmail.com";
root.campaign.campaignId = "IDss6604303";
var jsBody = new JavaScriptSerializer().Serialize(root);
request.AddHeader("X-Auth-Token", "api-key 948sdfsdfsdfsdfsdfs6");
request.AddParameter("application/x-www-form-urlencoded", "email=" + email + "&campaign=ID85104303", ParameterType.RequestBody);
var response = client.Execute(request);
Model:
public class Campaign
{
public string campaignId { get; set; }
}
public class RootObject
{
public string name { get; set; }
public string email { get; set; }
public Campaign campaign { get; set; }
}
There is no "connection" between the Request request and the JSON Object jsBody (or root). What you're sending is a query string.
Something like
email=test#gmail.com&campaign=ID85104303
This is defined by the line:
request.AddParameter("application/x-www-form-urlencoded", "email=" + email + "&campaign=ID85104303", ParameterType.RequestBody);
If you want to send your JSON, you need to change the line to:
request.AddParameter("application/json; charset=utf-8", jsBody, ParameterType.RequestBody);
I can't tell if this will already work, but so you're at least sending the right body and you should get a successful response or at least a better error message.
I am sending name, which is a string, and table data which is a 2d array
And I get the name just fine in th controller, but I can't seem to get the tableData.
This is how I create the table data
TableData
var tableData = new Array();
$('table tbody tr').each(function () {
var tableRow = new Array();
tableRow.push({ 'id: $(this).data('id') });
tableRow.push({ 'item': $(this).data('item') });
tableData.push(tableRow);
});
JavaScript
var data = { Name: name, TableData: tableData };
$.ajax({
type: 'POST',
url: url,
data: data
});
Controller
[HttpPost]
public void Add(string Name, string[][] TableData)
{
// Stuff
}
As always in an ASP.NET MVC application you could start by defining a view model that will reflect to your view logic:
public class MyViewModel
{
public string Name { get; set; }
public Ilist<MyViewModelItem> TableData { get; set; }
}
public class MyViewModelItem
{
public string Id { get; set; }
public string Item { get; set; }
}
then fix the way you are constructing your data on the client:
var tableData = [];
$('table tbody tr').each(function () {
tableData.push({
id: $(this).data('id'),
item: $(this).data('item')
});
});
and then the way you are sending this information to the controller (send it as a JSON payload to ensure that complex objects will be properly bound on the server as long as your view model respect the proper format):
$.ajax({
type: 'POST',
url: url,
data: JSON.stringify({ name: name, tableData: tableData }),
contentType: 'application/json'
});
and the last piece of the puzzle - the signature of your controller action:
[HttpPost]
public void Add(MyViewModel model)
{
// Stuff
}
I'm running the following AJAX call.
var submission = {};
submission.input = [];
submission.input.push({ Id: "{ab684cb0-a5a4-4158-ac07-adff49c0c30f}" });
submission.input.push({ Id: "{bb684cb0-a5a4-4158-ac07-adff49c0c30f}" });
$.ajax({
url: "http://" + "localhost:49642/Controller/Action",
data: submission
});
It works as supposed to and in my controller I can see two elements. However, the Id fields is all-zeros. I'm certain I failed to match the definition of the object on the server-side but I'm to annoyed and frustrated right now to generate more suggestions how to shove the data to the service.
The data model is like this.
public class Thingy
{
public Guid Id { get; set; }
public IEnumerable<Guid> Blobb { get; set; }
}
I've tried to use different bracket types, apostrophes and such enclosing the guids on client-side. To no avail. What can I have forgotten?!
Edit
I need to clarify the structural definition of my information object. The controller is set up to receive the following.
public ActionResult SelectionStorage(IEnumerable<Stuff> stuff)
{
Session["Stuff"] = stuff;
return null;
}
The definition of the Stuff class is more complex but the following will suffice as a POC.
public class Stuff
{
public Guid Id { get; set; }
public IEnumerable<Guid> Ids { get; set; }
public Dictionary<String, decimal> Amounts { get; set; }
}
So, on the client, I'm performing the following set up of the submitted data object.
var submission = {};
var subIds = [];
subIds.push("{ab684cb0-a5a4-4158-ac07-adff49c0c30f}");
subIds.push("{bb684cb0-a5a4-4158-ac07-adff49c0c30f}");
submission.input = [];
submission.input.push({
Id: "{cb684cb0-a5a4-4158-ac07-adff49c0c30f}",
Ids: subIds,
Amounts: null
});
Note that the Amounts will differ from null but that headache I haven't even got to, yet.
Edit 2
New try - a simpler approach. In JS I send the following.
var stuff = {};
stuff.input = [];
stuff.input.push("{ab684cb0-a5a4-4158-ac07-adff49c0c30f}");
stuff.input.push("{bb684cb0-a5a4-4158-ac07-adff49c0c30f}");
$.ajax({
url: ...,
data: stuff,
type: "POST",
success: ...,
error: ...
});
On recieving end in C# I have this.
public ActionResult MyAction(List<String> input) { ... }
This gives null. I can't see why.
You should be able to simplify the jquery. With what you have here you don't need the submission. If you are sending a complex list back to the controller you need to name your variables but since you are just sending a string back you don't need to do that. Try changing your data to
var input = [];
input.push("{ab684cb0-a5a4-4158-ac07-adff49c0c30f}");
input.push("{bb684cb0-a5a4-4158-ac07-adff49c0c30f}");
then in the ajax call
data: input,
or
data: Json.stringify(input);
then on your controller
public ActionResult Action(List<String> input){...
Edit:
try changing your jquery to this:
var stuff= {};
stuff.Id = "{cb684cb0-a5a4-4158-ac07-adff49c0c30f}";
stuff.Ids= [];
stuff.Ids.push("{ab684cb0-a5a4-4158-ac07-adff49c0c30f}");
stuff.Ids.push("{bb684cb0-a5a4-4158-ac07-adff49c0c30f}");
then in your ajax have data: stuff, or data: Json.stringify(stuff),
I need to post JSON data from the client to the application ASP.NET MVC 4, but the javascript code is run by user and transfer data from the site www.lotsalneschs.com to my server. For testing I used Google Chrome console panel.
Controller code:
public class HomeController : Controller
{
public ActionResult Index()
{
return View();
}
[HttpPost]
public JsonResult Save(List<NewsModel> items)
{
return Json(null);
}
}
public class NewsModel
{
public string Title { get; set; }
public string Content { get; set; }
public List<string> Tags { get; set; }
}
Javascript code:
function News() {
var arr = {};
var title = "items";
var tTitle = "Title";
var cTitle = "Content";
var tgTitle = "Tags";
arr[title] = [];
for (var i = 0; i < 10; i++) {
var n = {};
n[tTitle] = "Title №" + i;
n[cTitle] = "TEXT";
n[tgTitle] = [];
for (var j = 0; j < 5; j++) {
n[tgTitle].push("tag" + j);
}
arr[title].push(n);
}
return arr;
}
var news = News();
$.ajax({
url: 'http://localhost:28369/Home/Save',
type: 'POST',
dataType: 'json',
contentType: 'application/json',
data: JSON.stringify(news)
});
If I execute the script while being on the page localhost:28369/Home/Index everything works perfectly:
http://i.stack.imgur.com/RL1nR.png
But the execution of this script on any other page, for example stackoverflow.com does not break at the same breakpoint.
If I delete contentType in the script, get the following:
http://i.stack.imgur.com/4Hcyn.png
If I delete contentType and not use JSON.stringify to format my data, get the following:
http://i.stack.imgur.com/F1Ql7.png
How to fix this problem?
I think it has to do with your URL being hard coded to localhost. Try replacing your line
url: 'http://localhost:28369/Home/Save',
with
url: '#Url.Action("Save", "Home")',
Edit:
Thinking about it you should see what path is generated by the Url.Action. I think the issue is being run from a different server local host is pointing to that server and not your computer. If the Url.Action doesn't work then you should point it to a public facing address.
I have a link as follows.
#Html.ActionLink("Create Report", "Screenreport", "Reports", null, new { #class = "subNavA AddBorderTop", id = "screenReport", title = "Create Report" })
Once the link is clicked, I have a the following jQuery code which creates a JSON object and post the information.
$().ready(function () {
// Create Report fron the screen data
$("#screenReport").live("click", function (event) { GenerateScreenReport(this, event); });
}) /* end document.ready() */
function GenerateScreenReport(clikedtag, event) {
var table = $(".EvrakTable").html();
var screendata = tableParser(table);
var Screentable = { Screenlist: screendata };
var myurl = $(clikedtag).attr("href");
var title = $(clikedtag).attr("title");
$.ajax({
url: myurl,
type: 'POST',
data: JSON.stringify(Screentable),
dataType: 'json',
contentType: 'application/json',
success: function () { alert("Got it"); }
});
};
To Handle JSON I have the following two classes. Realize two classes in the same namespace
namespace MyProject.ViewModels
{
public class Screenrecord
{
public string Fname{ get; set; }
public string LName { get; set; }
public string Age { get; set; }
public string DOB { get; set; }
}
public class Screentable
{
public List<Screenrecord> Screenlist { get; set; }
}
}
ANd in my controller, I have the following code:
[HttpPost]
public FileStreamResult Screenreport(Screentable screendata)
{
MemoryStream outputStream = new MemoryStream();
MemoryStream workStream = new MemoryStream();
Document document = new Document();
PdfWriter.GetInstance(document, workStream);
document.Open();
document.Add(new Paragraph("Hello World"));
document.Add(new Paragraph(DateTime.Now.ToString()));
document.Close();
byte[] byteInfo = workStream.ToArray();
outputStream.Write(byteInfo, 0, byteInfo.Length);
outputStream.Position = 0;
return new FileStreamResult(outputStream, "application/pdf");
}
This code is supposed to gerate PDF.
if I leave [HttpPost] as it is, it does NOT generate PDF and it goes to /Screenreport page, however I see my JSON is passed to the controller properly.
(screendata is populated properly - in controller)
But if I comment out [HttpPost], it DOES generate a PDF but screendata (in controller) is null.
Can someone please explain whats's going on and help me figure it out. Thanksin advance.
You cannot use AJAX to download files, because javascript doesn't allow you to save the downloaded content.
To workaround this you need to take 2 steps.
First: make the HTTP Post request, and in the controller action we would store the File content in a Memory stream.Second: on success make another call by setting the window.location to the Download Action method
In your Controller create this 2 actions:
public ActionResult GenerateFile()
{
MemoryStream fileStream = new MemoryStream { Position = 0 };
//position = 0 is important
var fName = string.Format("File-{0}.xlsx", DateTime.Now.ToString("s"));
Session[fName] = fileStream;
return Json(new { success = true, fName }, JsonRequestBehavior.AllowGet);
}
public ActionResult DownloadFile(string fName)
{
var ms = Session[fName] as MemoryStream;
if (ms == null)
return new EmptyResult();
Session[fName] = null;
return File(ms, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", fName);
}
In your javascript:
$('#Donwload-button').click(function () {
data = JSON.stringify(YOURDATA);
$.ajax({
contentType: 'application/json; charset=utf-8',
dataType: 'json',
type: 'POST',
url: "/YOURCONTROLLER/GenerateFile",
data: data,
success: function (d) {
if (d.success) {
window.location = "/YOURCONTROLLER/DownloadFile" + "?fName=" + d.fName;
}
},
error: function () {
alert("Error");
}
});
});
I feel obligated to post my answer since I didn't hear from anyone. I ended up creating a form that includes a hidden input, then saved my json object in the hidden input and then submit the form. This time I will get input as an string not a json or xml.
var $hidInput = $("#dataToReport");
$hidInput.val(JSON.stringify(Screentable));
$('#frmScreenreport').submit();
Thanks all anyways.