I have a class
public class ConversionResultModel
{
public string ProcessId { get; set; }
public bool Result { get; set; }
public string Message { get; set; }
}
sending it to view using JSon
public ActionResult UploadFile(IEnumerable<HttpPostedFileBase> clientUpload)
{
string destinationPath = "";
JsonResult result = null;
var fileModel = new ConversionResultModel();
fileModel.ProcessId = "4558-95559-554";
fileModel.Result = true;
fileModel.Message = "test.pdf";
result = Json(new { fileModel }, "text/plain");
return result;
}
How to parse such JSon object at client side using JS or jQuery and read values?
I have tried to parse JSon object with code below but get Undefined error in alert
var obj = $.parseJSON(e.response);
alert(e.obj);
I receive JSon object like this
{"fileModel":{"ProcessId":"4558-95559-554","Result":true,"Message":null,"SourceFile":null,"ConvertedFileName":"test.pdf","ConvertedFileSize":1233444,"DownloadUrl":"http://localhost:2008/download?path=4558-95559-554","DeleteUrl":"http://localhost:2008/download?path=4558-95559-554"}}
You do not need to parse it. Just set data type to JSON during ajax request and then use received data object like entity and you easily can access to any property:
var id = data.ProcessId;
Anyway, using jQuery you can parse JSON string:
var data = jQuery.parseJSON(stringData);
P.S:
Use the following code sample for converting object to JSON in ASP.NET MVC:
return this.Json(fileModel);
http://api.jquery.com/jQuery.parseJSON/
In your case, I think you're getting back the correct JSON, but your alert is looking at the wrong object. Try alert(obj.SomeProperty) rather than alert(e.obj). e.obj doesn't exist, which is likely why you're getting an "undefined" error. For example, alert(obj.fileModel.ProcessId); should work.
Related
I am trying to call a WebAPI method from Angular 5 like this:
selectClaims(state: DataSourceRequestState):Observable<DataResult>
{
return this.http.get<GridDataResult>(`${this.apiUrl}/SelectClaims?${toDataSourceRequestString(state)}`);
}
Which calls the API method as expected. The API method is:
[Route("SelectClaims")]
[HttpGet]
public IHttpActionResult SelectClaims([FromUri][DataSourceRequest]DataSourceRequest ClaimsRequest)
{
if(ClaimsRequest == null)
ClaimsRequest=new DataSourceRequest { Page=1, PageSize=20 };
var result = _db.Claims.ToDataSourceResult(ClaimsRequest, c => { c.SortHistory(); return c; });
return Ok(result);
}
The trouble is that ClaimsRequest only de-serializes Page and PageSize correctly. Filters and Sorts don't come through:
Fiddler tells me that the URL from Angular is:
GET /api/v1/Claims/SelectClaims?filter=id~eq~2&page=1&sort=firstName-asc&pageSize=20 HTTP/1.1, but in the controller both filter and sort are null.
If I create a URL through Swagger like: 'http://localhost:50223/api/v1/Claims/SelectClaims?ClaimsRequest.page=1&ClaimsRequest.pageSize=11&ClaimsRequest.sorts=firstName-desc' I do see a sort array in the API method, but the "Member" field is null.
Any attempt to add a filter through Swagger like 'http://localhost:50223/api/v1/Claims/SelectClaims?ClaimsRequest.page=1&ClaimsRequest.pageSize=11&ClaimsRequest.filters=id~eq~2' results in a "Cannot create an instance of an interface." error.
The state is a DataSourceRequestState in the angular component from a Kendo Grid for Angular.
I have simulated this in a simple test program and everything works fine there. The only difference in my test program is that the API controller targets .Net Core and the real system targets .Net 4.6.1.
Do I have to de-serialize manually in .Net 4.6.1 for some reason, or is something else going on here?
It should be a POST not a GET. Something like this:
return this.http.post<GridDataResult>(`${this.apiUrl}/SelectClaims`, toDataSourceRequestString(state)});
I needed it to be a GET (URL) so i created a new object
public class GridParamaterBinder
{
public int Page { get; set; }
public int PageSize { get; set; }
public string Filter { get; set; }
public string Sort { get; set; }
public DataSourceRequest ToDataSourceRequest(IConfigurationProvider mapper, Func<string, string> OverDefaultParamaterMapping)
{
DataSourceRequest result = new DataSourceRequest();
result.Page = Page;
result.PageSize = PageSize;
result.Sorts = GridDescriptorSerializer.Deserialize<SortDescriptor>(Sort);
result.Filters = FilterDescriptorFactory.Create(Filter);
return result;
}
}
and used it instead of the Telerik effort.
in API I Bind it like so
public virtual DataSourceResult Get([FromUri]GridParamaterBinder request)
And then used it like
DataSourceResult results = query.ToDataSourceResult(request.ToDataSourceRequest(), r => (r)));
Thanks #KevDevMan for your solution. I found this example,
then I changed my API controller like this and it worked like a charm :
[HttpGet, Route("for-kendo-grid")]
public DataSourceResult GetProducts([System.Web.Http.ModelBinding.ModelBinder(typeof(WebApiDataSourceRequestModelBinder))] DataSourceRequest request)
explanation here
I found that using [fromapi] attribute I can pass one complex object.
when I try to pass list of complex objects it doesn't work.
in the client side I use breeze. server side is webapi.
How can I do this?
You can create one DTO which has property for your list of objects
public class CreateUserDto
{
public string Name {set;get;}
public List<RoleDto> Roles {set;get;}
public CreateUserDto()
{
this.Roles = new List<RoleDto>();
}
}
public class RoleDto
{
public int Id {set;get;}
public string Name {set;get;}
}
And you can use that as the argument of your Web api endpoint
public HttpResponseMesssage Save(CreateUserDto model)
{
//Check model.Roles now
// to do : Return a response
}
From client, you can send data like this.(Assuming you have jQuery library loaded to your page)
var data { Name : "TestName",Roles:[]}
data.Roles.push(new { Id:1,Name:"Admin"});
data.Roles.push(new { Id:2,Name:"Editor"});
$.post("YourEndpointHere",data,function(response){
// do something with response
});
Modelbinding will take care of converting the posted form data to an instance of CreateUserDto in your Save method. You can access model.Roles property to get the list of complex objects you wanted.
you can use Dictionary as below:
[HttpPost]
public IQueryable<Product> GetProducts(Dictionary<string, object> data)
{
var categoryId = Convert.ToInt32(data["categoryId"]);
var category = _context.Categories.Single(a => a.ID == categoryId);
var galleryId = Convert.ToInt32(data["galleryId"]);
var langId = Convert.ToInt32(data["langId"]);
var searchStr = data["str"];
return category.Products.Where(a => a.GalleryID == galleryId, a.LanguageID == langId, a.Description.Contains(searchStr))
}
I'm following Scott Allen's MVC4 course on PluralSight (I'm using MVC5 and WebAPI2 but they should be the same) and I am trying to pass an object via HTTP PUT. The model binder should bind it, but I am getting NULL for the parameter.
public HttpResponseMessage PutObjective(int id, [FromBody] Objective objective)
{
if (ModelState.IsValid && id == objective.ObjectiveID)
{
//todo: update - look up id, replace text
return Request.CreateResponse(HttpStatusCode.OK, objective);
}
else
{
return Request.CreateResponse(HttpStatusCode.BadRequest);
}
}
and in my front-end javascript I am doing the following (I'm creating an object for testing, so ignore 'objective' passed in):
var updateObjective = function (objective) {
var myobj = { "ObjectiveID": "3", "ObjectiveDescription": "test" };
return $.ajax(objectiveApiUrl + "/" + objective.ObjectiveID, {
type: "PUT",
data: myobj
});
}
My class looks like this:
public class Objective
{
public int ObjectiveID { get; private set; }
public string ObjectiveDescription { get; set; }
public Objective (int Id, string Desc)
{
this.ObjectiveID = Id;
this.ObjectiveDescription = Desc;
}
}
Any thoughts on why 'objective' in the backend is always 'null' ?
I've done what Scott Allen is doing, even tried adding in [FromBody] but no luck. $.ajax should have the correct content type by default I understand, so no need to set it.
I had Fiddler2 but I'm unsure as to what I am looking at to be honest. I can see my object as JSON being sent to the backend.
Well, if you're familiar with Model Binding you'll have seen the issue in my Objective class:
public int ObjectiveID { get; private set; }
with a private set, no instance can be created of the Objective class. To make it work, the 'private' access specifier needs to be removed.
What needs to happen really is that Objective becomes ObjectiveViewModel, and we convert what comes back to an Objective domain object (which may have more properties than we need for this screen). This can have a private set.
I am trying to POST form data which consists of few string variable and binary array.
Below is the Model for the form data.
public class FileModel
{
public string Path { get; set; }
public byte[] File { get; set; }
}
Below is my Web API Controller.
[Route("")]
public IHttpActionResult Post([FromBody]FileModel media)
{
// Can I use ??
byte[] requestFile = media.File;
string requestFilePath = media.Path;
//Process the above variables
return Ok();
}
I would like to know Can I use the following code to de-serialize the following code snippet to to read the values from the JSON payload including the binary data?
byte[] requestFile = media.File;
string requestFilePath = media.Path;
If Yes, Do I need to define any formatter class to get it working?
I normally use POSTMAN to test my RESTful endpoints.
Is it possible to use POSTMAN still to POST binary array? May be not need to write my own client
You'll need to use a serializer to serialize complex objects (multiple fields) as content for a Http Request.
For your code snippet to read the object from the content you can use this:
var requestContent = Request.Content.ReadAsAsync<FileModel>(GetJsonSerializer()).Result;
Here's the serializer boilerplate code.
private JsonMediaTypeFormatter GetJsonSerializer()
{
JsonSerializerSettings settings = new JsonSerializerSettings()
{
PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.All,
TypeNameHandling = Newtonsoft.Json.TypeNameHandling.All
};
return new JsonMediaTypeFormatter() { SerializerSettings = settings };
}
I'm not sure how to use POSTMAN to test this. A simple .net client would be:
var Client = new HttpClient();
Client.BaseAddress = new Uri("localhost"); //whatever your endpoint is
FileModel objectToSend = new FileModel();
var objectContent = new ObjectContent<FileModel>(objectToSend, GetJsonSerializer() );
var response = Client.PostAsync("uri", objectContent);
You are able to use POSTMAN to test binary file input. Selecting the body tab, you can then pick the radio button "binary" and then choose file.
I want to display data in Listbox without using any DLL.And my webservice responding in json format.
My Web service Response is as below.it has more than 800 records
[
{
"st_id":"1",
"st_name":"name xyz"
},
{
"st_id":"2",
"st_name":"name ABC"
},
{
"st_id":"3",
"st_name":"name HIJK"
},
{
"st_id":"4",
"st_name":"name OPQ"
},
]
my Class for the data is as below
[DataContract]
public class Student
{
[DataMember=("st_id")]
public bool st_id { get; set; }
[DataMember=("st_name")]
public string st_name { get; set; }
}
i m trying serialize object using DataContractJsonSerializer & m getting WS response in Stream.But i am not able to serialize.Suggest links or basic tutorial for Serilize and Deserilize of the json
DataContractJsonSerializer stdserialize =
new DataContractJsonSerializer(typeof(Student));
Student stuser = (Student)stdserialize.ReadObject(responseStream);
so please help for the json response parsing & suggest link for datacontract and all which gives knowledge from basics.
Thanks,
You declared st_id as a bool, but the type of data you're trying to deserialize is string (which can be converted to numbers - not to booleans). Try declaring it as string and it should work.
Also, the response is an array of objects, so the type you should use is Student[]:
DataContractJsonSerializer stdserialize =
new DataContractJsonSerializer(typeof(Student[]));
Student stuser = (Student[])stdserialize.ReadObject(responseStream);