Get Json from Web api and pass to partial view from controller - c#

At the moment I have this as my code:
public ActionResult Search(SearchModel model)
{
string url = "http://10.0.2.31/testwebapi/api/data";
WebClient wc = new WebClient();
wc.QueryString.Add("forename", model.Forename);
wc.QueryString.Add("surname", model.Surname);
wc.QueryString.Add("caseid", model.CaseId);
wc.QueryString.Add("postcode", model.Postcode);
wc.QueryString.Add("telephone", model.Telephone);
wc.QueryString.Add("email", model.Email);
wc.QueryString.Add("title", model.Title);
var data = wc.UploadValues(url, "POST", wc.QueryString);
var responseString = Encoding.Default.GetString(data);
return PartialView("~/Views/Shared/SearchResults.cshtml", responseString);
}
public class RootObject
{
public int Caseid { get; set; }
public string Title { get; set; }
public string Forename { get; set; }
public string Surname { get; set; }
public string Postcode { get; set; }
public string Telephone { get; set; }
public string Email { get; set; }
public string DOB { get; set; }
public string Mobile { get; set; }
public string MaritalStatus { get; set; }
public string LoanPurpose { get; set; }
public bool CourtesyCall { get; set; }
public string isOpen { get; set; }
}
im not sure where i am going wrong i want it to be able to pull that data from the web api (which returns a json file). then what i want to do is send that data through to my partialview where a #foreach statement will put it into a table but i cant seem to get it to send the data it is interperating it as a string and i dont know why
this is how it is returning:
#model string
#{
Layout = null;
}
#foreach(var Case in Model)
{
<p>#Case</p>
}
Partial view code.
This is what my partial now looks like:
#model IEnumerable<Savvy_CRM_MVC.Models.RootObject>
#{
Layout = null;
}
#foreach (var m in Model)
{
<p>#m</p>
}
which when i run through the for each is gives me this Savvy_CRM_MVC.Models.RootObject

The problem is that you are binding you model to the raw JSON string.
you need to deserialize the JSON string to your RootObject class and use RootObject as the model for your view.
the following code user Newtonsoft JSON.net to deserialize the string;
var rootObjects = JsonConvert.DeserializeObject<RootObject[]>(responseString);
return PartialView("~/Views/Shared/SearchResults.cshtml", rootObjects);
and you view changes
#model IEnumerable<RootObject>
You are also going to need to change you view to display the properties of your model.

Related

How to serialize JSON from Form (multipart/form-data) to list?

When I try to post multipart/form-data with my file and JSON, then lists are empty in model, but Alias, WorkerName and File are correctly serialized.
[HttpPost]
[Route("add")]
[Consumes("multipart/form-data")]
public async Task<JobAddDto> Add([FromForm] JobInputInternalDto model)
{
var form = Request.Form;
//do stuff with model
}
In Request.Form those values are correctly sent:
How can I serialize data from form to lists in my model?
I have my JobInputInternalDto written as:
public class JobInputDto
{
public string Alias { get; set; } = string.Empty;
public string WorkerName { get; set; } = string.Empty;
public IEnumerable<ParameterDto> Parameters { get; set; } = new List<ParameterDto>();
public IEnumerable<WorkflowOptionsDto> Workflow { get; set; } = new List<WorkflowOptionsDto>();
}
public class JobInputInternalDto : JobInputDto
{
public IFormFile? Payload { get; set; } = null;
}
With ParameterDto as:
public class ParameterDto
{
public int Order { get; set; }
public string Name { get; set; } = string.Empty;
public string Value { get; set; } = string.Empty;
}
And WorkflowOptionsDto as:
public class WorkflowOptionsDto
{
public int Order { get; set; }
public string WorkerName { get; set; } = string.Empty;
public string? WorkerVersion { get; set; } = null;
public IEnumerable<ParameterDto> Parameters { get; set; } = Enumerable.Empty<ParameterDto>();
}
What i can guess by your Request.Form image is that you've sent the Parameters data with Json format like:
{ Order: 0, Name: "Test Name 0", Value: "Test Value 0" }
But since you're using
[Consumes("multipart/form-data")]
As such, C# expects the model to be form formatted, and therefore a list of objects should have the following format:
As you can see in the following image, using form format, C# is able to bind the data properly:

C# ASP.NET MVC can not pass 2 objects in TempData from one controller to another controller

I have code in a C# application that uses JSON.SerializeObject to store data in TempData in one controller and then I use JsonConvert.DeserializeObject in a second controller. This is the code in the first controller:
TempData["participantData"] = JsonConvert.SerializeObject(participantData);
return RedirectToAction("Index", "MainPage");
In the above code, I serialize an object called participantData. participantData is defined like this:
ParticipantLoadData participantData = new ParticipantLoadData();
The ParticipantLoadData class looks like this:
public class CurrentParticipant
{
public string comp_first_day_of_year { get; set; }
public string comp_rate_of_return { get; set; }
public string ss_LastName { get; set; }
public string ss_FirstName { get; set; }
public string ss_SocSec { get; set; }
public string ss_Bal { get; set; }
public string ss_Pending { get; set; }
public string ss_LoanOB { get; set; }
public string ss_VstBal { get; set; }
public string ss_ValDate { get; set; }
public int ss_LoanFund { get; set; }
public string fld_CY_IEXP { get; set; }
public string fld_Salary { get; set; }
public string th_last_contribution { get; set; }
public string th_last_contribution_date { get; set; }
}
This all works fine as I am able to retrieve TempData["participantData"] from within the MainPage controller.
When I try to send a second object to TempData, I end up generating a "This site can't be reached" error. This is what I added:
I tried to add a second object to the TempData. I created a List where the Fund Class looks like this:
public class Fund
{
public int FundNumber { get; set; }
public string FundName { get; set; }
}
Then, I populated a list of type Fund with this code:
List<Fund> FundList = new List<Fund>();
var webRoot = _env.WebRootPath + "/txt";
var FILENAME = System.IO.Path.Combine(webRoot, "fund_list.txt");
{
foreach (string line in System.IO.File.ReadLines(FILENAME))
{
var oneFund = new Fund();
oneFund.FundNumber = int.Parse(line.Substring(1, 4));
if (oneFund.FundNumber > 0)
{
oneFund.FundName = FundNameException(line.Substring(6, line.Length - 6));
FundList.Add(oneFund);
}
}
}
This code loads 2000 elements into the FundList.
When this loop completes, I execute these lines of code:
TempData["FundList"] = JsonConvert.SerializeObject(FundList, Formatting.Indented);
TempData["participantData"] = JsonConvert.SerializeObject(participantData);
return RedirectToAction("Index", "MainPage");
I have a break point set at the return, which I hit. When I look at the TempData["FundList"], it appears to contain the correct data in the correct format. I also have a break point set in controller MainPage on the first line of code within the ActionResult Index() which never gets hit.
Any idea why adding this second object to TempData would be causing an issue?
Any insight is greatly appreciated.

Unable to implement API in ASP.NET Core

(Note: I am a beginner!)
I am doing an ASP.NET Core Website and have to show the list of all countries with their travel advisory scores in a table.
I can't display the data using a Travel Advisory API. Each country is a separate key and are different classes when I paste the JSON as classes.
How can I call each country's class (eg. AU) and display the data under the country using a loop? The problem is that there are too many countries so I hope to use a loop for this. As you can see in the code below, I can only show one country at a time as each country is a different class.
Basic API endpoint: https://www.travel-advisory.info/api
Optional parameter: https://www.travel-advisory.info/api?countrycode=AU (restricts the result list to a single country)
My TravelAdvisory controller's action method:
public async Task<ActionResult> Index()
{
string countryCode = "AU"; //I plan to have multiple country codes in a loop,
//just haven't done so yet as I have issues showing the data for all country codes
// Make Web API call to get a list of travel advisories
HttpClient client = new HttpClient();
client.BaseAddress = new Uri("https://www.travel-advisory.info");
HttpResponseMessage response = await client.GetAsync("/api");
if (countryCode != null)
{
response = await client.GetAsync("/api?countrycode=" + countryCode);
}
if (response.IsSuccessStatusCode)
{
string data = await response.Content.ReadAsStringAsync();
Rootobject model = JsonConvert.DeserializeObject<Rootobject>(data);
float score = model.data.AU.advisory.score;
//here, I can only get the score for one country since class names are different.
List<float> dataList = new List<float>();
dataList.Add(score);
TempData["Score"] = Convert.ToString(score);
return View();
}
else
{
return View(new List<Data>());
}
}
TravelAdvisory model classes:
public class Rootobject
{
public Api_Status api_status { get; set; }
public Data data { get; set; }
}
public class Api_Status
{
public Request request { get; set; }
public Reply reply { get; set; }
}
public class Request
{
public string item { get; set; }
}
public class Reply
{
public string cache { get; set; }
public int code { get; set; }
public string status { get; set; }
public string note { get; set; }
public int count { get; set; }
}
public class Data
{
public AD AD { get; set; }
public AE AE { get; set; }
public AF AF { get; set; }
public AG AG { get; set; }
public AI AI { get; set; }
public AL AL { get; set; }
public AM AM { get; set; }
...
My code:
Model: https://controlc.com/da48a2be
Controller: https://controlc.com/51d938c7
You need to add a parameter to the Index method like this and write your logic accordingly.
public async Task<ActionResult> Index(string countryCode)
{
And you can use the code in if and else, you you want to get records for all countires if countryCode is null or emotry string.
HttpResponseMessage response = null;
if (string.IsNullOrEmpty(countryCode))
{
response = await client.GetAsync("/api);
}
else
{
response = await client.GetAsync("/api?countrycode=" + countryCode);
}
Edit:
You can use reflection to get all the properties and proceed further.
Data data = ...;
foreach (var prop in data.GetType().GetProperties())
{
...
}

How to bind JSON response to Models in ASP MVC?

So I'm new to the ASP/.NET/C# game, so would definitely appreciate any help you might be able to offer me. I've currently got a Controller called "ProjectController.cs" that has an action "Index" which is supposed to pass a list of "projects" to the view. I've gone ahead and created the controller, the action, the API call and the view. However, per the screenshots provided - I am running into an error with the API call itself - I'm attempting to return a list of models to the controller to be passed to the view. I am doing this through by loading a JSON response from the http://10000ft.com api. Any ideas why I am continually getting jammed up when trying to create/validate new project objects against the model?
ProjectController.cs:
namespace MVCProject1.Controllers
{
public class ProjectController : Controller
{
// GET: Project
public ActionResult Index()
{
List<Models.Project> projects = APICalls.GetAllProjects();
return View(projects);
}
}
}
Project Controller / Index Action View:
#{
ViewBag.Title = "Project Index";
}
#model IEnumerable<MVCProject1.Models.Project>
#foreach (var project in Model)
{
#project.name <br />
}
ProjectModel.cs:
namespace MVCProject1.Models
{
public class Project
{
public int id { get; set; }
public bool archived { get; set; }
public object archived_at { get; set; }
public string description { get; set; }
public string guid { get; set; }
public string name { get; set; }
public object parent_id { get; set; }
public object phase_name { get; set; }
public string project_code { get; set; }
public string secureurl { get; set; }
public string secureurl_expiration { get; set; }
public int settings { get; set; }
public int timeentry_lockout { get; set; }
public string ends_at { get; set; }
public string starts_at { get; set; }
public object deleted_at { get; set; }
public string created_at { get; set; }
public string updated_at { get; set; }
public bool use_parent_bill_rates { get; set; }
public string thumbnail { get; set; }
public string type { get; set; }
public bool has_pending_updates { get; set; }
public string client { get; set; }
public string project_state { get; set; }
}
}
APICalls.cs:
namespace MVCProject1
{
public class APICalls
{
private const string baseUrl = "https://api.10000ft.com/api/v1/{0}?&auth=temp12345=&{1}";
#region PROJECTS
public static List<Models.Project> GetAllProjects()
{
string requestUrl = string.Format(baseUrl, "projects", "&per_page=200");
var resultString = RestClient.makeAPICall(requestUrl);
var resultObject = JsonConvert.DeserializeObject(resultString);
List<Models.Project> projects = new List<Models.Project>();
foreach (var project in resultObject.data)
{
projects.Add(project);
}
return projects;
}
#endregion
}
}
RESTClient.cs:
namespace MVCProject1
{
public static class RestClient
{
public static string makeAPICall(string requestUrl)
{
var syncClient = new WebClient();
var content = syncClient.DownloadString(requestUrl);
Trace.WriteLine(content.ToString());
return content;
}
}
}
Image of error I'm receiving
I think that you have an issue with deserialization of product list.
Try
var projects = JsonConvert.DeserializeObject<List<Models.Project>>(resultString);
instead of
var resultObject = JsonConvert.DeserializeObject(resultString);
List<Models.Project> projects = new List<Models.Project>();
foreach (var project in resultObject.data)
{
projects.Add(project);
}
and check that projects value is not null and no errors occures while deserialization

How to bind multilevel json data to a repeater in asp.net or converting json data to data table

I want to bind the Json data to the repeater I know only one process that is converting the Json data to data table and then binding data but here I am receiving multilevel json data i do't know how to convert them to data table
input json data:
{"apiAvailableBuses":
[{"droppingPoints":null,"availableSeats":40,"partialCancellationAllowed":false,"arrivalTime":"01:00 AM","cancellationPolicy":"[{\"cutoffTime\":\"1\",\"refundInPercentage\":\"10\"},{\"cutoffTime\":\"2\",\"refundInPercentage\":\"50\"},{\"cutoffTime\":\"4\",\"refundInPercentage\":\"90\"}]","boardingPoints":[{"time":"07:40PM","location":"K.P.H.B,Beside R.S Brothers","id":"2238"}],"operatorName":"Apple I Bus","departureTime":"8:00 PM","mTicketAllowed":false,"idProofRequired":false,"serviceId":"6686","fare":"1000","busType":"Hi-Tech A/c","routeScheduleId":"6686","commPCT":9.0,"operatorId":203,"inventoryType":0},
{
"droppingPoints":null,"availableSeats":41,"partialCancellationAllowed":false,"arrivalTime":"06:00 AM","cancellationPolicy":"[{\"cutoffTime\":\"1\",\"refundInPercentage\":\"10\"},{\"cutoffTime\":\"2\",\"refundInPercentage\":\"50\"},{\"cutoffTime\":\"4\",\"refundInPercentage\":\"90\"}]","boardingPoints":[{"time":"08:00PM","location":"Punjagutta,","id":"2241"}],"operatorName":"Royalcoach Travels","departureTime":"8:00 PM","mTicketAllowed":false,"idProofRequired":false,"serviceId":"6736","fare":"800","busType":"VOLVO","routeScheduleId":"6736","commPCT":9.0,"operatorId":243,"inventoryType":0}
I am trying to convert it to data table by
public void getavailablebuses()
{
string url = string.Format(HttpContext.Current.Server.MapPath("files/getavailablebuses.json"));
using (WebClient client = new WebClient())
{
string json = client.DownloadString(url);
var result = JsonConvert.DeserializeObject<RootObject>(json);
string mm = JObject.Parse(json).SelectToken("apiAvailableBuses").ToString();
// var boardingpoint = JObject.Parse(mm).SelectToken("boardingPoints").ToString();
var Availablebuses = JObject.Parse(json).SelectToken("apiAvailableBuses").ToString();
DataTable dt = (DataTable)JsonConvert.DeserializeObject(Availablebuses, (typeof(DataTable)));
}
public class apiresult
{
public string message { get; set; }
public string success { get; set; }
}
public class RootObject
{
public apiresult apiStatus;
public List<apiAvailableBuses> apiAvailableBuses{ get; set; }
// public string apiAvailableBuses { get; set; }
}
public class apiAvailableBuses
{
public string serviceId { get; set; }
public string fare { get; set; }
public string busType { get; set; }
public string departureTime { get; set; }
public string operatorName { get; set; }
public string cancellationPolicy { get; set; }
public List<boardingpoints> boardingpoints { get; set; }
public string droppingPoints { get; set; }
public string inventoryType { get; set; }
public string routeScheduleId { get; set; }
public int availableSeats { get; set; }
public string arrivalTime { get; set; }
public Boolean idProofRequired { get; set; }
public Boolean partialCancellationAllowed { get; set; }
public int operatorId { get; set; }
public double commPCT { get; set; }
public string mTicketAllowed { get; set; }
}
public class boardingpoints
{
public string location { get; set; }
public string id { get; set; }
public string time { get; set; }
}
public class cancellationPolicy
{
public string cutoffTime { get; set; }
public string refundInPercentage { get; set; }
}
Here in the data table I am unable to get the boarding points, dropping points and cancellation policy
if I load cancellation policy as list or JObject I am getting error
so here I am loading cancellation policy as string.
but I am unable to load boarding points and dropping points.
Please help with this I am scratching my head from two days. Thanks in advance
"I know only one method to bind data to a repeater i.e data table." So this is a perfect opportunity to learn other ways, wouldn't you say?
Why don't you work with the result of JsonConvert.DeserializeObject<RootObject>(json);? This is a RootObject that has a property called apiAvailableBuses which seems to be exactly what you need to bind to your repeater, no?
By the way, a bit of code review:
apiresult and apiAvailableBuses violate Microsoft's rules WRT class names: those should be in PascalCase. Same for the properties of apiresult, e.g. message and success. Same for the properties of apiAvailableBuses.
RootObject has a public field: apiStatus. That probably needs to be a a property with a getter/setter.
Moreover, apiAvailableBuses is plural, which is incorrect, since the data therein is of only one bus. Same for boardingpoints: the class contains data for a single point, not multiple.
Be consistent: if you use string, then also use bool and not Boolean.

Categories

Resources