c# mvc 5 call json web service and save on database - c#

Greetings i want to call a web api that returns a json string from From Controller and i want to map it on a class so i can save the data on the database.But i dont understand how to map each data on the json with the class.
I only get the message that is succeed.
my code is:
public ActionResult API()
{
var client = new WebClient();
var text = client.DownloadString("https://www.example.com/api/all-users?name=user%20&pass=password");
wclients wclients = JsonConvert.DeserializeObject<wclients>(text);
if (wclients.message == "success")
{
ViewBag.name = ("name = " + wclients.name);
}
return View();
}
my view is this:
#foreach (var item in ViewBag.name) {
<tr>
<td>
#item
</td>
</tr>
}
The Response from web api is:
{"status":true,"message":"success","data":[{"name":"test test","email":"senthil#nscript.in","phone":"1234567890","affiliated_id":null,"account":{"real":[{"login":"1001175","pass":"4pJccK8AUWw8"},{"login":"3001180","pass":"4AeCqasw7jX2"},{"login":"3001182","pass":"fS2tf6Gsej7C"}]

try the below code:
public ActionResult API()
{
var client = new WebClient();
var text = client.DownloadString("https://www.example.com/api/all-users?
name=user%20&pass=password");
var wclients = JsonConvert.DeserializeObject<dynamic>(text);
if (wclients.message == "success")
{
var data = wclients.data;
}
return View();
}

wclients.name will never contain anything because there is not a property called "name" at the top level of the JSON object structure.
To access the name property you would need to enumerate through the data array (which should exist as a property on the wclients class) and get the name from there.
Update
As per the example below:
public class wclients
{
public bool status { get; set; }
public string message { get; set; }
public IEnumerable<Account> data { get; set; }
}
public class Account
{
public string name { get; set; }
public string email { get; set; }
public string phone { get; set; }
}
public ActionResult API()
{
var client = new WebClient();
var text = client.DownloadString("https://www.example.com/api/all-users?name=user%20&pass=password");
wclients clients = JsonConvert.DeserializeObject<wclients>(text);
if (wclients.message == "success")
{
ViewBag.name = clients.data;
}
return View();
}
and in the view
#foreach (var item in ViewBag.name)
{
<tr>
<td>
#item.name
</td>
</tr>
}

The JSON must map directly to your C# class.
For example, if the JSON has the following:
"name":"test test",
"email":"senthil#nscript.in"
Then your class (eg Person.cs) must have the same properties:
public class Person{
public string name {get;set}
public string email {get;set}
}
Then you would do:
Person person = JsonConvert.DeserializeObject<Person>(json);
In your example, you probably need wclients.data
if (wclients.message == "success")
{
ViewBag.name = ("name = " + wclients.data.name);
}
Finally, the name wclients suggests there are multiple... in which case:
var names = new List<string>();
foreach(var client in wclients){
if (client.message == "success")
{
names.Add("name = " + client.data.name);
}
}

Related

Mixed up my Two Models, Null Reference in Post Request (ASP.NET MVC)

I'm trying to present a table with a list of rows from the database, as well as a small form option for the user to add an additional db row. I made two Models in order to both hold the table rows and capture the form. I'm not having problems with the table model, just the form model.
So I'm confident the problem is in my Controller; I am new to MVC and this is the first time I've seen two models in the same VM... I've been going back and forth making small changes to things, but I keep getting a Null Reference Error in my Controller.
VM:
namespace User.ViewModel
{
public class UploadDocumentTemplatesViewModel
{
public string TemplateName { get; set; }
public string Comments { get; set; }
}
public class TemplateModel
{
public UploadDocumentTemplatesViewModel NewTemplate { get; set; }
public List<UploadDocumentTemplatesViewModel> Templates { get; set; }
}
}
View (UploadDocumentTemplates.cshtml):
#using (Html.BeginForm("AddNewTemplate", "User", FormMethod.Post, new { enctype = "multipart/form-data", id = "NewTemplateForm"}))
{
#Html.AntiForgeryToken()
<div>
<input type="text" class="form-control" rows="5" id="TemplateName" value="#Model.NewTemplate.TemplateName">
<label for="comments">Comments:</label>
<textarea class="form-control" rows="5" id="comments" name="#Model.NewTemplate.Comments"></textarea>
<button id="AddTemplate" onclick="AddNewTemplate()" name="Add Template">Add Template</button>
</div>
}
<table>
<tbody>
#{ foreach (var template in Model.Templates)
{
<tr id="tr_#template.DocumentTemplateId">
<td>#template.TemplateName</td>
<td>#template.Comments </td>
<td>#template.IsActive </td>
}
<script>
function AddNewTemplate() {
$("#NewTemplateForm").submit();
}
</script>
Controller:
public class UserController : Controller
{
public ActionResult UploadDocumentTemplates()
{
var model = entity.DocumentTemplates.Select(x => new UploadDocumentTemplatesViewModel()
{
DocumentTemplateId = x.DocumentTemplateId,
TemplateName = x.TemplateName,
Comments = x.Comments,
});
var _obj = new TemplateModel();
var templatelist = _entities.GetTemplates();
_obj.Templates = new List<UploadDocumentTemplatesViewModel>();
foreach (var template in templatelist)
{
_obj.Templates.Add(new UploadDocumentTemplatesViewModel()
{
TemplateName = template.TemplateName,
Comments = template.Comments,
});
}
_obj.NewTemplate = new UploadDocumentTemplatesViewModel();
return View(_obj);
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult AddNewTemplate(TemplateModel vModel)
{
var template = new DocumentTemplates();
template.TemplateName = vModel.NewTemplate.TemplateName;
template.Comments = vModel.NewTemplate.Comments;
entity.DocumentTemplates.Add(template);
entity.SaveChanges();
return View("~/User/UploadDocumentTemplates.cshtml", vModel);
}
}
I hit a Null Reference at this line in my Post method in the Controller:
template.TemplateName = vModel.NewTemplate.TemplateName;
The vModel.NewTemplate.TemplateName is null. Can anyone help me with this?
Thank you so much!
SOLUTION:
The NRE did get fixed with Andy's help (see answer). My further issue was fixed after I populated the new VM with the fields I was using in my form.
namespace Example.Areas.ViewModel
{
public class UploadDocumentTemplatesViewModel
{
public long DocumentTemplateId { get; set; }
public string TemplateName { get; set; }
public string Comments { get; set; }
}
public class TemplateModel
{
public string TemplateName { get; set; }
public string Comments { get; set; }
public HttpPostedFileBase TemplateFile { get; set; }
public List<UploadDocumentTemplatesViewModel> Templates { get; set; }
}
}
In the controller I populated the TemplateModel and sent that to the View:
public ActionResult UploadDocumentTemplates()
{
var templateList = Repository.GetTemplates();
var _obj = new TemplateModel
{
Templates = templateList.Select(x => new UploadDocumentTemplatesViewModel()
{
DocumentTemplateId = x.DocumentTemplateId,
TemplateName = x.TemplateName,
Comments = x.Comments
}).ToList()
};
return View(_obj);
}
Then I put #using Example.Areas.ViewModel.TemplateModel on my View and used Model.Templates for the table, and Model.TemplateName and Model.Comments in the form.
Add a breakpoint in the line where you hit the Null Reference and check if vModel.NewTemplate has a valid instance.
You can add a constructor in TemplateModel class to create a new instance of UploadDocumentTemplatesViewModel()
namespace User.ViewModel
{
public class UploadDocumentTemplatesViewModel
{
public string TemplateName { get; set; }
public string Comments { get; set; }
}
public class TemplateModel
{
public TemplateModel()
{
NewTemplate = new UploadDocumentTemplatesViewModel();
}
public UploadDocumentTemplatesViewModel NewTemplate { get; set; }
public List<UploadDocumentTemplatesViewModel> Templates { get; set; }
}
}
OR
create an instance after instantiating template:
var template = new DocumentTemplates();
template.NewTemplate = new UploadDocumentTemplatesViewModel();

json response through MongoDb

When the below API method is called through the API
public IActionResult FirstStudent()
{
var collection = this.database.GetCollection<BsonDocument>("students");
var filter = Builders<BsonDocument>.Filter.Eq("RollNo", "1");
var document = collection.Find(filter).First();
var firstStudent= document.ToJson();
return Ok(firstStudent);
}
the response has Content-Type as text/plain.
I need the Content-Type as application/json.
Any suggestions?
the easiest thing to do would be to create a student model and simply return an ok result with the student model like this:
public class Student
{
[BsonRepresentation(BsonType.ObjectId)]
public string Id { get; set; }
public int RollNo { get; set; }
public string Name { get; set; }
}
public IActionResult FirstStudent()
{
var collection = this.database.GetCollection<Student>("Student");
var filter = Builders<Student>.Filter.Where(s => s.RollNo == 1);
var document = collection.Find(filter).First();
return Ok(document);
}

How can I display a model property name that is coming from the database?

I currently am pulling a list of url's from a view using Entity Framework 5 and MVC 5. I have the view populating all the links but I need each link to display their 'LinkState' names like in my model so it will output:
Alabama
Georgia
etc.
with the link attached to the LinkState. Instead of the view foreach loop saying State Link. I cant get my model/controlled to pull the correct information.
Repository:
public class LinkRepository
{
private readonly LinkLibrary _entities = new LinkLibrary ();
public LinkRepository()
{
_entities = new LinkLibrary ();
}
public List<LinkModels> RetrieveStateLink(string year)
{
return
_entities.vw_URLLibrary.Where(s => s.YEAR.Equals(year) && s.URL_TYPE.Equals("United States")).Select(m => new LinkModels()
{
UrlLink = m.LinkLocation
}).ToList();
}
}
Model
public class LinkModels
{
public string LinkYear { get; set; }
public string LinkState { get; set; }
public string UrlLink { get; set; }
public string LinkType { get; set; }
public List<string> ListOfUrls{ get; set; }
}
Controller
public ActionResult GetStateLinks()
{
var stateLink = new List<string>();
var model = rr.RetrieveStateLinks("2014").Select(m=> m.UrlLink).ToList();
foreach (var s in model)
{
stateLink.Add(s);
}
var rm = new LinkModels();
rm.ListOfUrls = stateLink;
return View(rm);
}
View
#foreach (var item in Model.StateLinkList)
{
<td>
State Link
</td>
}
Your issue is that you are returning a List of strings as opposed to a list of LinkModels. I updated the repository to return the url and link name
removed some unneccessary code in your controller and updated it to work with a list of LinkObjects. Then updated the view to display the info.
You will have to update your view #model List<LinkModels> instead of #model List<string>
public class LinkRepository
{
private readonly LinkLibrary _entities = new LinkLibrary ();
public LinkRepository()
{
_entities = new LinkLibrary ();
}
public List<LinkModels> RetrieveStateLink(string year)
{
return
_entities.vw_URLLibrary.Where(s => s.YEAR.Equals(year) && s.URL_TYPE.Equals("United States")).Select(m => new LinkModels()
{
LinkState = m.LinkState,
UrlLink = m.LinkLocation
}).ToList();
}
}
public ActionResult GetStateLinks()
{
var stateLink = new List<LinkModels>();
var model = rr.RetrieveStateLinks("2014");
return View(model);
}
#foreach (var item in Model)
{
<td>
#item.LinkState
</td>
}
Controller
public ActionResult GetStateLinks()
{
var model = rr.RetrieveStateLinks("2014");
return View(model);
}
View (change your view model to list of LinkModels)
#foreach (var item in Model)
{
<td>
#item.LinkState
</td>
}

Html table not populating from ViewModel

I am trying to populate an HTML table with data from a table in my database. The issue is simply that the HTML table is not getting populated with any data.
Here is the ViewModel:
public class TestViewModel
{
public string MatchedId { get; set; }
public string UnmatchedId { get; set; }
public string Auth { get; set; }
public DateTime CreditDate { get; set; }
public string CreditNumber { get; set; }
public decimal CreditAmount { get; set; }
public DateTime DeniedDate { get; set; }
public int DeniedReasonId { get; set; }
public string DeniedNotes { get; set; }
}
Controller Action:
[HttpPost]
public ActionResult UploadValidationTable(HttpPostedFileBase csvFile)
{
var inputFileDescription = new CsvFileDescription
{
SeparatorChar = ',',
FirstLineHasColumnNames = true
};
var cc = new CsvContext();
var filePath = uploadFile(csvFile.InputStream);
var model = cc.Read<Credit>(filePath, inputFileDescription);
try
{
var entity = new Entities();
//model here is the .csv, doesn't have anything to do with this issue
foreach (var item in model)
{
var tc = new TemporaryCsvUpload
{
Id = item.Id,
CreditAmount = item.CreditAmount,
CreditDate = item.CreditDate,
CreditNumber = item.CreditNumber,
DeniedDate = item.DeniedDate,
DeniedReasonId = item.DeniedReasonId,
DeniedNotes = item.DeniedNotes
};
entity.TemporaryCsvUploads.Add(tc);
}
entity.SaveChanges();
System.IO.File.Delete(filePath);
//This is where the database table is getting filled
entity.Database.ExecuteSqlCommand("Insert into CsvReport Select p.Id as MatchedId, case when p.Id is null then t.Id end as UnmatchedId, p.Auth,p.CreditDate, p.CreditNumber,p.CreditAmount, p.DeniedDate,p.DeniedReasonId, p.DeniedNotes from TemporaryCsvUpload t left join PermanentTable p on p.Id = t.Id;");
TempData["Success"] = "Updated Successfully";
}
catch (LINQtoCSVException)
{
TempData["Error"] = "Upload Error: Ensure you have the correct header fields and that the file is of .csv format.";
}
return View("Upload");
}
View:
#model IEnumerable<TestProject.TestViewModel>
#if (Model != null)
{
foreach (var item in Model.Where(x => x.IdMatched != null))
{
<tr>
<td>
#item.MatchedId
</td>
<td>
#item.Auth
</td>
<td>
#item.CreditDate
</td>
<td>
#item.CreditNumber
</td>
<td>
#item.CreditAmount
</td>
<td>
#item.DeniedDate
</td>
<td>
#item.DeniedReasonId
</td>
<td>
#item.DeniedNotes
</td>
</tr>
}
}
It's a little weird because I am populating the database with an SQL command. What am I missing here? Do I need to try and pass it through the controller action? Let me know if you need more information. Thanks!
Edit
I tried to pass the instance through, but I may still be doing it incorrectly:
var testModel = new TestViewModel();
return View("Upload", testModel);
Here is what its padding through:
public class TestViewModel
{
public IEnumerable<Test> Test { get; set; }
}
Made an answer so essentially the view doesn't know what to render you need to pass an actual filled model (in your case an IEnumerable to the view). This can be done using the method:
View("Upload", viewModelList);
Controller.View docs on MSDN
It looks like you are not adding any data to your view model.
If your view model is a collection of Test objects, you need to add some
Test objects to the collection.
var model = new TestViewModel()
{
Test = new List<Test>() { new Test(), new Test(), ... }
}
return View("Upload", model);

Move data between dual listbox in asp.net mvc

Hi I'm new in MVC now working with dual listboxes. I wanted to move the data from listbox1 to listbox2. For that I'm using the following code:
View
<tbody>
<tr>
<td>
<%:Html.HiddenFor(m=>m.objMemberAccessRights.Id) %>
<%:Html.ListBoxFor(model =>model.objMemberAccessRights.AvailableSelected, newMultiSelectList(Model.objMemberAccessRights.AvailableNames, "Id", "InstituteName", Model.objMemberAccessRights.AvailableSelected), new { size="8"})%>
</td>
<td>
<br/>
<%:Html.ActionLink(">>", "AddNames", "MemberDetails") %>
<br/>
<br/>
<%:Html.ActionLink("<<", "RemoveNames", "MemberDetails") %>
</td>
<td>
<%:Html.ListBoxFor(model=>model.objMemberAccessRights.RequestedSelected,newMultiSelectList(Model.objMemberAccessRights.RequestedNames,"Id","InstituteName",Model.objMemberAccessRights.RequestedSelected), new { size="8"}) %>
</td>
</tr>
</tbody>
Controller
//
// GET: /MemberDetails/Create
public ActionResult Create()
{
MemberDetailsWrapper MD = new MemberDetailsWrapper();
MD.objMemberAccessRights = newMemberAccessRights{ AvailableNames = getAllInstituteNameList(), RequestedNames = new List<InstituteInformation>() };
return View(MD);
}
//AddNames
public ActionResult AddNames(MemberDetailsWrapper MD, string add)
{
ModelState.Clear();
RestoreSavedState(MD);
if (!add.Equals(">>"))
{
if (MD.objMemberAccessRights.AvailableSelected != null)
{
var names = getAllInstituteNameList().Where(p => MD.objMemberAccessRights.AvailableSelected.Contains(p.InstituteName));
MD.objMemberAccessRights.RequestedNames.AddRange(names);
MD.objMemberAccessRights.AvailableSelected = null;
}
}
SaveState(MD);
return View(MD);
}
//RemoveNames
public ActionResult RemoveNames(MemberDetailsWrapper MD, string remove)
{
ModelState.Clear();
RestoreSavedState(MD);
if (!remove.Equals("<<"))
{
if (MD.objMemberAccessRights.RequestedSelected != null)
{
MD.objMemberAccessRights.RequestedNames.RemoveAll(p => MD.objMemberAccessRights.RequestedSelected.Contains(p.InstituteName));
MD.objMemberAccessRights.RequestedSelected = null;
}
SaveState(MD);
return View(MD);
}
#regionSupportFuncs
public void SaveState(MemberDetailsWrapper MD)
{
MD.objMemberAccessRights.SavedRequested = string.Join(",", MD.objMemberAccessRights.RequestedNames.Select(p =>p.InstituteName).ToArray());
////Available Names = All - Requested
MD.objMemberAccessRights.AvailableNames = getAllInstituteNameList().Except(MD.objMemberAccessRights.RequestedNames).ToList();
}
//RestoreSavedState
public void RestoreSavedState(MemberDetailsWrapper MD)
{
MD.objMemberAccessRights.RequestedNames = new List<InstituteInformation>();
if (!string.IsNullOrEmpty(MD.objMemberAccessRights.SavedRequested))
{
string[] nameids = MD.objMemberAccessRights.SavedRequested.Split(',');
var name = getAllInstituteNameList().Where(p =>nameids.Contains(p.InstituteName));
MD.objMemberAccessRights.RequestedNames.AddRange(name);
}
}
#endregion
In model:
public class InstituteInformation
{
public int Id { get; set; }
public string InstituteName { get; set; }
}
public class MemberAccessRights
{
public int Id { get; set; }
public List<InstituteInformation> AvailableNames { get; set; }
public string[] AvailableSelected { get; set; }
public List<InstituteInformation> RequestedNames { get; set; }
public string[] RequestedSelected { get; set; }
public string SavedRequested { get; set; }
}
Here When I click on >> button then this button returns the Error:
Object reference not set to an instance of an object. Description: An
unhandled exception occurred during the execution of the current web
request. Please review the stack trace for more information about the
error and where it originated in the code. Exception Details:
System.NullReferenceException: Object reference not set to an instance
of an object.
Source Error:
Line 170: public void RestoreSavedState(MemberDetailsWrapper MD)
Line 171: {
Line 172: MD.objMemberAccessRights.RequestedNames = new List<InstituteInformation>();
Line 173:
Line 174: if (!string.IsNullOrEmpty(MD.objMemberAccessRights.SavedRequested))
Your object is null (MD.objMemberAccessRights that is). MVC will not pass that back in the WHOLE model with out tweaking. especially lists
The simplest solution is to assume the lists are empty rebuild the lists after each request. By the looks of your code you are not persisting the data but i assume you will at the end?
What you need to do is persist the item after it has been moved and then requery the dB to recreate the lists.
You can avoid all this dB chattiness using jquery but that has its own challenges.

Categories

Resources