I have a API Json data that contains a lot of information, but I only need to map one attribute to my model class, say Programname, I don't care of other information. I am using Json converter to DeserializeObject the API data. Is it possible to only map partial Json data to my model class? Right now, I receive error message as below if I only map one attribute of the Json data. Thanks.
InvalidOperationException: The model item passed into the ViewDataDictionary is of type 'System.Collections.Generic.List`1[WebApplication2.Program]', but this ViewDataDictionary instance requires a model item of type 'System.Collections.Generic.IEnumerable`1[WebApplication2.Models.Program]'.
public class Program
{
public int Prog_id { get; set; }
public string Programname { get; set; }
}
Controller:
public async Task<IActionResult> Index()
{
var Client = new HttpClient();
Client.DefaultRequestHeaders.Accept.Clear();
Client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("appllication/json"));
HttpResponseMessage res = await Client.GetAsync("my url");
if (res.IsSuccessStatusCode)
{
var result = res.Content.ReadAsStringAsync().Result;
List<Program> programs = JsonConvert.DeserializeObject<List<Program>>(result);
return View(programs);
}
else
{
throw new Exception(res.ReasonPhrase);
}
}
View
#model IEnumerable<WebApplication2.Models.Program>
<h1>Index</h1>
<p>
<a asp-action="Create">Create New</a>
</p>
<table class="table">
<thead>
<tr>
<th>
Program
</th>
<th></th>
</tr>
</thead>
<tbody>
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.Programname)
</td>
</tr>
}
</tbody>
</table>
change view model to list and fix a namespace
#model List<WebApplication2.Program>
and IMHO use await instead of .Result
var result = await res.Content.ReadAsStringAsync();
List<Program> programs = JsonConvert.DeserializeObject<List<Program>>(result);
return View(programs);
I figured it out what the problem was now. The word "Program" is a reserved word in asp.net core. After I changed the Program to something else, it works. :/
Related
I have a Model.
public class ViewInput
{
public List<List<String>> cells;
//Other stuff
}
This model data is passed to a Razor generated HTML view. Note that when the model is passed to the view, a tested and confirmed non-zero sized 2D list is passed to the view.
#model MvcMovie.Models.ViewInput
#*Stuff*#
#using (Html.BeginForm("GenerateDecisionTree", "Home", FormMethod.Post))
{
<p>
<table id="mainTable">
#for (var i = 0; i < Model.cells.Count(); i++)
{
<tr>
#for (var j = 0; j < Model.cells[i].Count(); j++)
{
<td>
#Html.TextBoxFor(m => m.cells[i][j])
</td>
}
</tr>
}
</table>
</p>
<div>
<br><input type="submit" name="submit" class="btn btn-danger" value="Generate Decision Tree" />
</div>
}
after which a post is handled by a controller
[HttpPost]
public String GenerateDecisionTree(ViewInput vi)
{
var test = vi.cells[0][0];//EXCEPTION - THE 2D LIST IS
return "Hi There";
}
Running this code results in an exception on the very first line of the controller code because the list of lists, called "cell", is empty for some reason. It should not be empty because we are posting data on a non zero 2D list.
I am well aware of this post and this link but they dont seem to answer my question.
Can any body please help me solve this problem
You need to add get;set; to cells:
public class ViewInput
{
public List<List<string>> cells { get; set; }
//Other stuff
}
result:
Heres the controller
[ApiController, Route("api/reports"), Authorize]
public class ReportsController : Controller
with the methods
[HttpPost, Route("download")]
public async Task<IActionResult> Download(string[] ids)
{
var cd = new System.Net.Mime.ContentDisposition("attachment") { FileName = "downloads.json" };
Response.Headers.Add("Content-Disposition", cd.ToString());
return Ok(await CreateDocumentsOnIds(ids));
}
[HttpGet, Route("{id}/download")]
public async Task<IActionResult> Download(string id)
{
var cd = new System.Net.Mime.ContentDisposition("attachment") { FileName = $"document_{id}.json" };
Response.Headers.Add("Content-Disposition", cd.ToString());
return Ok(await CreateDocumentOnId(id));
}
Which works fine for one Id:
<table class="table is-fullwidth">
<thead>
<tr>
<th>Link</th>
<th>Dato</th>
</tr>
</thead>
<tbody>
#foreach (var doc in documents)
{
<tr>
<td>#doc.Url</td>
<td>#doc.Updated.ToShortDateString()</td>
<td><a class="button is-link" Color=#Color.Primary href=#($"/api/reports/{doc.Id}/download")>Download</a></td>
</tr>
}
</tbody>
</table>
But I want the possibility to download several documents as one file. And in order for the controller to be able to create this file, it needs ids of the files. Therefore I somehow need to be able to send an object containing these ids to the controller, from the client memory. Is this possible to do with forms?
I'm just starting out with MVC, JSON, AJAX, etc and as a side project have been trying to create a data viz dashboard.
Today I followed this guide on how to pass a simple table of data from SQL as JSON to my view: http://techfunda.com/howto/292/list-records-using-json
It mostly worked: the JsonResult comes through from my controller and contains the values but not the property names.
This causes a problem because I'm referencing the property names when I process the data for display in JavaScript.
Here's the SQL data:
Here's my Model:
public partial class vw_Dash_ChartData : IEnumerable<object>
{
[Key]
[JsonProperty(PropertyName = "Classification")]
public string Classification { get; set; }
[JsonProperty(PropertyName = "Count")]
public int Count { get; set; }
public IEnumerator<object> GetEnumerator()
{
yield return Classification;
yield return Count;
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
}
(You'll notice I tried to manually set the [JsonProperty(...)] stuff...it didn't help.)
And here's my JsonResult:
public JsonResult ChartDataJson()
{
var data = new List<vw_Dash_ChartData>();
data = db.vw_Dash_ChartDatas.ToList();
var jsonData = Json(data, JsonRequestBehavior.AllowGet);
return jsonData;
}
(Initially I was sending the data straight through from my DbContext but then thought perhaps it would help to use my vw_Dash_ChartData model. It didn't make a difference).
My view looks like the following:
#{
ViewBag.Title = "Charts";
AjaxOptions options = new AjaxOptions
{
//Confirm = "Are you sure?",
LoadingElementId = "divLoading",
OnSuccess = "processDataMethod",
Url = Url.Action("ChartDataJson")
};
}
<script type="text/javascript">
function processDataMethod(data) {
var output = $("#dataZone");
output.empty();
for (var i = 0; i < data.length; i++) {
var chartData = data[i];
output.append("<tr><td>" + chartData.Classification + "</td><td>" + chartData.Count + "</td></tr>");
}
}
</script>
<div>
<table>
<thead>
<tr>
<th>Classification</th>
<th>Count</th>
</tr>
</thead>
<tbody id="dataZone">
</tbody>
</table>
</div>
#using (Ajax.BeginForm(options))
{
<div id="divLoading" style="color: red; font-size: larger;">
Loading...
</div>
<div>
<button type="submit" id="btnClicky" >Clicky</button>
</div>
}
<script>
$("#btnClicky").trigger("click");
</script>
When I load the page, this is what I get:
and this is the JSON object shown in the browser developer tools;
Any tips/ideas gratefully received! Also, if I'm doing anything stupid do let me know as I'd like to learn best practice for this stuff.
How about?
var jsonData = Json(data.Select(x=> new {
Classification = x.Classification,
Count = x.Count
})
);
return jsonData;
I'm new to MVC and getting this depressing error when I try to insert buttons into a table.
I have for my .cshtml ViewModel in EditorTemplates:
#model EditorForSample.Models.ProductViewModel
<tr>
<td>#Html.CheckBoxFor(m => m.Selected)</td>
<td colspan="1">
#Model.Name
#Html.HiddenFor(m => m.Name)
</td>
<td>
#Model.Password
#Html.HiddenFor(m => m.Password)
</td>
<td>
#Html.RadioButtonFor(e => e.Locked, true)</td>
<td>
#Html.RadioButtonFor(e => e.Locked, false)</td>
</tr>
And for the model:
public class ProductViewModel
{
public bool Selected{ get; set; }
public string Name { get; set; }
public string Password { get; set; }
public bool Locked { get; set; }
}
I'm getting a 404 error in the .cshtml even though I cannot determine why the syntax is wrong.
Edit: Okay, it turns out that the above actually does work when I manually change the URL and instead my problem is one of the routing randomly changing of its own accord and trying to redirect to the model view CSHTML.
You should send the viewmodel to the view like this.
ProductViewModel productViewModel= new ProductViewModel();
//populate productViewModel with values
View(productViewModel);
also make sure that you added the correct namespace at the top of your file
like this :
using Project.Models;
EDIT:
example for adding Radiobutton in view for same model property:
#Html.RadioButtonFor(model => model.Selected, "false")
#Html.RadioButtonFor(model => model.Selected, "true")
In controller it should be like:
[HttpPost]
public ActionResult Index(MyViewModel model)
{
return Content("IsFemale: " + model.Selected);
}
I think this will inspire you. Of course you have to modify it according to the way you need.
I want to pass the results of a query (JSON) from a controller to a partial view, that's why I created a strongly type as follows:
public class Suivi_Client
{
public string ClientID { get; set; }
public string Activite { get; set; }
public string ClientName { get; set; }
}
// list
public class Suivis
{
public List<Suivi_Client> List_Clients { set; get; }
}
Then the partial view :
#model IEnumerable<Project.Models.Suivi_Client>
<html>
<body>
<table border=1>
<thead>
<tr>
<th>
ID
</th>
<th>
Name
</th>
<th>
Activite
</th>
</tr>
</thead>
#foreach(var item in Model){
foreach (var pop in item.List_Clients)
{
<tr>
<td >
#Html.DisplayFor(modelItem => pop.ClientID)
</td>
< <td >
#Html.DisplayFor(modelItem => pop.ClientName)
</td>
<td >
#Html.DisplayFor(modelItem => pop.Activite)
</td>
</tr>
}
}
</table>
</body>
</html>
here is the action method:
public ActionResult Partial_suivi(string clients)
{
IEnumerable<Suivis> PopModel;
var activit = (from x in frh.productivites
join y in frh.Clients on x.action equals y.ClientName
where x.action.Equals(clients)
select new { x.actionID,x.Activité,y.ClientName,y.Responsable,y.TempsCible,x.tempsmoy_ }).Distinct().ToArray();
PopModel = activit;
return PartialView(PopModel);
}
but I have this error : Can not convert type 'AnonymousType # 1 []' to 'Project.Models.Suivis
how can I resolve this error ?
There's a couple issues here.
In your Action Method, you are trying to pass an IEnumerable<Suivis> to your view.
But your view is expecting an IEnumerable<Suivi_Client>.
The next problem is your linq query is selecting (transforming) into an anonymous object, but you're trying to put it into an IEnumerable<Suivis>.
I'm going to take a guess that what you want to do is make your linq query select into an IEnumerable<Suivi_Client> so that your view can do it's work. To do that you would change your code to something similar to this
IEnumerable<Suivi_Client> PopModel = (from x in frh.productivites
join y in frh.Clients on x.action equals y.ClientName
where x.Action.Equals(clients)
select new Suivi_Client
{
Activite = x.Activite,
ClientName = y.ClientName,
ClientID = ??
}).Distinct();
return PartialView(PopModel);
There are a lot of unknowns from the code you provided, and you're using objects that you didn't show in your code snippets. If you could explain what you want your linq query to do actually do, I'm sure someone could post a more complete/better example of how to achieve what you're after.