Json data coming back null - c#

Good evening, guys! I've got an odd one.
Long story short, I'm sending a post from a java script client-side to get an integer back from my C# Controller, but the response.data is coming back null. The twist is that both the C# method and the javascript/jquery function are literally copied and pasted from another project where both of them work. The project they're taken from is a VS2010 project, and they're pasted into a VS2012 project. I'm not sure if this is the issue, but it could be related. The integer is fetched correctly in the C# and none of the information is missing. Even more mysteriously, the success message is coming back correctly to the response object client-side. However the response.data object is null, and throws an exception.
Any and all help is very much appreciated. Thanks!
This is the method in the C#:
[HttpPost]
public JsonResult GetMaxFileSize()
{
int MaxFileSize = 0;
// Get max file size.
string MaxPatientFileSizeInMegsString = System.Web.Configuration.WebConfigurationManager.AppSettings["MaxFacilityLogoFileSizeInMegs"];
MaxFileSize = int.Parse(MaxPatientFileSizeInMegsString);
return Json(new AjaxResponse(true, "Success.", new { maxFileSize = MaxFileSize }));
}
And this is the javascript/jquery function:
function getMaxFileSize() {
$.post(settings.actions.getMaxFileSize, function (response) {
var maxFileSize = 0;
// Assign the correct size to the hidden field.
if (response.success) {
maxFileSize = response.data.maxFileSize;
$(settings.selectors.maxFileSizeHiddenInput).val(maxFileSize);
}
// Assign 0 to max file size: user cannot upload files.
else {
$(settings.selectors.maxFileSizeHiddenInput).val(maxFileSize);
}
});
}

Works fine here!
TestController.cs
public class AjaxResponse
{
public AjaxResponse(bool success, object data)
{
this.success = success;
this.data = data;
}
public bool success { get; set; }
public object data { get; set; }
}
[HttpPost]
public ActionResult Ajax()
{
return Json(new AjaxResponse(true, new { num = 5 }));
}
Index.cshtml
$.post('#Url.Action("Ajax", "Test")', function (response) {
var num = 0;
debugger;
// Assign the correct size to the hidden field.
if (response.success) {
num = response.data.num;
$('h2').html(num);
}
// Assign 0 to max file size: user cannot upload files.
else {
$('h2').html(num);
}
});
JSON response in FireBug:
{"success":true,"data":{"num":5}}

Related

Upload file in angular / web API

I created a function that add a new user with Angular/WebAPI , so in angular i send the object like this :
AddUser(person : person):Observable<person>
{
return this.http.post<person>(this.baseUrl,person);
}
and in WebAPI i got the data :
[HttpPost]
public async Task<ActionResult<Person>> PostPerson(Person person)
{
Now I want to add a picture of each user, and i don't know how it's gonna be the objet in angular, should i add a property imageProfile as File which i'm not sure if it's possible , or it should be a string of the uploaded file.
export class person {
idPerson:number=0;
fname : string ="" ;
lname : string ="";
password : string ="";
idCategory? :number;
nameCategory:string="";
imageProfile :
}
That's very good info from Codemaze, as always. The remark from Lavstsen is not correct, there's no need for a separate call.
For example, you could have a form linked to the structure of the person-type:
initializeForm() {
this.personForm = this.form.group({
fname: [''],
})
}
In your onSubmit-method, you seize the date from your form and put in a dto, in this example through a getPersonDto-method
private getPersonDto(): PersonDto {
let dto = new PersonDto();
dto.fname = this.imageForm.controls.fname.value;
return dto;
}
and next you can solve it like this:
const formData = new FormData();
formData.append('Imagefile', this.selectedFile, this.selectedFile.name);
formData.append('fname', personDto.fname); // needs to be strings => toString()
this.personApiClient.uploadImageFile(this.personId, formData)
.subscribe((res: any) => {
this.uploadOrDeleteResults = res;
this.showToastrMessageSuccess("PAGES.COMMON.TOASTR.TITLE.SUCCESSFULCREATE", "PAGES.COMMON.TOASTR.MESSAGE.SUCCESSFULCREATE");
},
(error) => {
this.crudHasErrors = true;
this.errorHttpErrorResponse = error;
this.errors = this.errorHttpErrorResponse.error;
},
you don't need the dto-step as such, but if you structurally always use dto's in your application, it would make more sense
Take care and good luck
I have another workaround but this will only work for very small files where you don't need upload percentage to show on UI.
I have my controller like this:
[HttpPost("/api/sign-up")]
public void SaveUser([FromForm] UserModel info)
{
_logger.LogDebug(null, "Hello", info); // Just to see contents of info object in debugger
}
and make your model like this:
public class UserModel
{
[FromForm(Name = "avatar")]
public IFormFile Avatar { get; set; }
[FromForm(Name = "email")]
public string Email { get; set; }
}

Using the Same Class to Store Data From Multiple Runs of a Function

On my project, I have an ajax method which triggers a function several times (all one the same run). For example, if the user presses a button, it triggers the Ajax and the function gets data for 10 seconds. After this, the user can press this button again and this will trigger the Ajax method again and will aquire more data for 10 and so forth. On each trigger, I have to store this data somehow and at the end of all the runs I will combine and store at my DB.
My problem is that If I create a class with all the runtimes, every time that I enter this function I reinitialize the class losing my previous data. So my idea at this point is something like:
I call a function this way:
Front end side:
function ReadsSerial() {
$.ajax({
url: "/Home/ReadsSerial",
type: 'POST',
data: { sintraining: gTrained },
success: function (result) {
alert(result.name);
},
error: function () {
alert("error");
}
});
return false;
};
And on my Back End I have a function like this:
[HttpPost]
public ActionResult ReadsSerial(string sintraining)
{
try
{
sintraining = Int32.Parse(sintraining);
}
catch (FormatException)
{
Console.WriteLine($"Unable to parse '{sintraining}'");
}
if (sintraining == 0)
{
// Call the constructor that has no parameters.
HandGesturesStorage0 handGesturesStorage = new HandGesturesStorage0();
handGesturesStorage.HandGesture0 = all;
}
if (sintraining == 1)
{
HandGesturesStorage1 handGesturesStorage = new HandGesturesStorage1();
handGesturesStorage.HandGesture1 = all;
}
if (sintraining == 2)
{
HandGesturesStorage2 handGesturesStorage = new HandGesturesStorage2();
handGesturesStorage.HandGesture2 = all;
}
And my classes are like this:
public class HandGesturesStorage0
{
public string HandGesture0 { get; set; }
}
public class HandGesturesStorage1
{
public string HandGesture1 { get; set; }
}
public class HandGesturesStorage2
{
public string HandGesture2 { get; set; }
}
But I feel that it must be a better way! If I have 10 run times I will have to create 10 if elses and 10 classes. Any ideas?
static List<HandGesturesStorage> myStogae;
[HttpPost]
public ActionResult ReadsSerial(string sintraining)
{
if (myStogae == null)
{
myStogae = new List<HandGesturesStorage>();
}
int st;
try
{
st = Int32.Parse(sintraining);
myStogae.Add(new HandGesturesStorage(sintraining));
}
catch (FormatException)
{
Console.WriteLine("Unable to parse '{sintraining}'");
}
}
public class HandGesturesStorage
{
public string HandGesture { get; set; }
public HandGesturesStorage(string sintraining)
{
this.HandGesture = sintraining;
}
}

Retrieving data appended to formData in C#

In this scenario:
var xhr = new XMLHttpRequest();
var fd = new FormData();
fd.append("file", document.getElementById('fileUpload').files[0]);
fd.append("PhoneId", '1234');
xhr.open("POST", '/Main/Upload', true);
xhr.send(fd);
xhr.addEventListener('load', function (event) {
var test = event.target.response;
})
I have a file upload along with an integer attached. My controller is:
public ActionResult Upload(Model newModel)
{
NewFiles files = new NewFiles ();
try
{
HttpPostedFileBase file = Request.Files[0];
}
catch(Exception)
{}
}
public class newModel
{
public int FileID { get; set; }
public string ReturnAction { get; set; }
public HttpPostedFileBase fileUpload { get; set; }
public int PhoneId { get; set; }
}
The uploaded file gets recognized, but what do I need in C# to view the uploaded PhoneId?
Your syntax is a bit off in the controller and won't compile. Changing the controller to the following syntax should work. This shows how to access the POSTed file and the model properties.
[HttpPost]
public ActionResult Upload(newModel model, HttpPostedFileBase file)
{
// Check the file is valid.
if (file == null || file.ContentLength == 0 || string.IsNullOrEmpty(file.FileName))
ModelState.AddModelError("fileUpload", "Invalid file uploaded.");
// Access model properties as you wish, like this:
int phoneID = model.PhoneId;
return null;
}
A couple of extra things to improve your code:
Generally speaking, when defining a class, the name of it should be in the format of CapitalizeEachWord.
It would be a lot easier if you used jQuery for your AJAX request rather than the normal JavaScript way of doing it. By using the normal JavaScript way, you're having to manually assign form properties to a FormData object, wheras with jQuery you can simpily do $("#formID").serialize().
it will work
string phoneId = Request.Form.Get("PhoneId");

How to keep CheckBox value after a get?

In my ASP.NET MVC 5 website i have this situation:
I have a GridView that i can get just the default rows or all the rows(including the deleted ones). Im trying to control that using a CheckBox in the ribbon of the view called 'cbxGetAll'.
So, here is my script:
<script>
function OnCommandExecuted(s, e) {
if (e.item.name == "cbxGetAll") {
if (e.parameter) {
window.location.href = '#Url.Action("Index",new {getAll = true})';
return;
} else {
window.location.href = '#Url.Action("Index",new {getAll = false})';
return;
}
}
</script>
And my Action:
public ActionResult Index(bool? getAll)
{
if (getAll != null && (bool) getAll)
{
//Return Without Filter
}
else
{
//Return With Filter
}
}
I change the getAll parameter in the URL and it works well.
But the problem is that when the ActionResult completes, it reloads the page (of course) and then i lost the checkbox state.
How can i deal with this?
It's all about view models. You should be returning a view model that has the value of your checkbox, and have your view use that value. If you are also returning data, simply place the data (whatever it is) inside your view model as well.
Example:
public class MyViewModel
{
public bool GetAll { get; set; }
public SomeDataModel[] MyData { get; set; }
}
public ActionResult Index(bool? getAll)
{
SomeDataModel[] data;
if (getAll != null && (bool) getAll)
{
var data = GetSomeData(true);
}
else
{
var data = GetSomeData(false);
}
return View(new MyViewModel() { MyData = data, GetAll = getAll == true });
}

print custom List in JavaScript

I have a custom list earthquakes which contains a list of earthquakes. How do I parse this in JavaScript in order to add it to innerHtml and display on the screen. The problem is that I cannot get this to display on the screen in a div. When it parses I get no result because my javascript is wrong and if I try just printing the result i get [Object object]
So the flow goes input from textbox -> web service -> list to javascript
earthquakes class:
public class earthquakes
{
public string eqid { get; set; }
public double magnitude { get; set; }
public double lng { get; set; }
public string source { get; set; }
public DateTime date { get; set; }
public int depth { get; set; }
public double lat { get; set; }
}
dataEarthquakes class
public class dataPostalCodes
{
public List<postalCodes> postalCodes { get; set; }
}
WebService:
public static dataEarthQuakes getEarthquakes(dataPostalCodes postalCodes)
{
double lat = postalCodes.postalCodes[0].lat;
double lng = postalCodes.postalCodes[0].lng;
Uri address = new Uri(String.Format(FindEarthquakes, lat, 0, lng, 0));
WebClient client = new WebClient();
string jsonResponse = string.Empty;
jsonResponse = client.DownloadString(address.AbsoluteUri);
var results = JsonConvert.DeserializeObject<dataEarthQuakes>(jsonResponse);
return results;
}
Javascript:
function OnLookupComplete(e) {
var result = e;
var weatherData = new Sys.StringBuilder();
var line;
for (var property in result.dataPostalCodes) {
line = String.format("<b>{0}:</b> {1}<br/>",
property, result.dataPostalCodes[property]);
weatherData.append(line);
}
$get('divResult').innerHTML = weatherData.toString();
}
Json string:
{"earthquakes":[{"eqid":"2010utc5","magnitude":7.7,"lng":97.1315,"src":"us","datetime":"2010-04-06 20:15:02","depth":31,"lat":2.3602}, {"eqid":"2009kdb2","magnitude":7.6,"lng":92.9226,"src":"us","datetime":"2009-08-10 17:55:39","depth":33.1,"lat":14.0129},{"eqid":"2010zbca","magnitude":7.6,"lng":123.533,"src":"us","datetime":"2010-07-23 20:51:11","depth":576.3,"lat":6.4939},{"eqid":"2010xkbv","magnitude":7.5,"lng":91.9379,"src":"us","datetime":"2010-06-12 17:26:50","depth":35,"lat":7.7477},{"eqid":"c0000rxc","magnitude":7.4,"lng":143.7392,"src":"us","datetime":"2010-12-21 16:19:41","depth":14.9,"lat":26.8656},{"eqid":"2010zbcd","magnitude":7.4,"lng":123.2677,"src":"us","datetime":"2010-07-23 21:15:08","depth":616.7,"lat":6.7489},{"eqid":"2010wbaq","magnitude":7.4,"lng":96.0805,"src":"us","datetime":"2010-05-09 03:59:44","depth":61.4,"lat":3.7284},{"eqid":"2007hvbq","magnitude":7.4,"lng":142.6846,"src":"us","datetime":"2007-09-28 11:38:58","depth":261.3,"lat":21.98},{"eqid":"2010zbbz","magnitude":7.3,"lng":123.4788,"src":"us","datetime":"2010-07-23 20:08:11","depth":604.5,"lat":6.7079},{"eqid":"2007xvam","magnitude":7.3,"lng":126.292,"src":"us","datetime":"2007-01-21 10:27:42","depth":10,"lat":1.2071}]}
As no.good.at.coding said in the comment, if your weatherData object contains the correct data, then it might be as simple as:
$('#divResult').html(weatherData.toString());
Another option may be to call parseJSON on your json object and then use jquery's each function to iterate through the results:
var results = $.parseJSON(e);
$(results).each(function (i, val) {
$('#divResult').append('<p>' + val.eqid + '<p>'); // can add markup here for magnitude and other properties
});
If you aren't sure what your objects are in javascript, firebug is a great tool for debugging (or you could use the Developer Tools that are built in to Chrome).
You didn't state an exact problem, but hopefully this will help get you on the right track.
Here's what I might do:
$.get('my-webservice-url',
function(data) {
OnLookupComplete(data['earthquakes']);
},
'json');
function OnLookupComplete(e) {
var weatherData = new Sys.StringBuilder();
for(var i=0;i<e.length;i++) {
var line;
for (var property in e[i].dataPostalCodes) {
line = String.format("<b>{0}:</b> {1}<br/>",
property, e[i].dataPostalCodes[property]);
weatherData.append(line);
}
}
$('#divResult').html(weatherData.toString());
}
The idea here is that you make your call to your web service and indicate to jQuery that the response expected is JSON (this is useful in case you aren't setting the content-type header correctly in the response from the server).
Once the GET request completes, jQuery will call your callback function (the anonymous function you can see in the call to $.get(). From your JSON example, I see that you expect an object earthquakes which is an array of objects of earthquake details.
The function then calls OnLookupComplete() with each the earthquakes array.
OnLookupComplete() then iterates over each earthquake, builds the right string and appends it to the StringBuilder. Finally, once all earthquakes have been dealt with, it appends the complete set of formatted lines to the div with the id divResult.

Categories