How to get Json Data from IPinfodb.com with MVC WebService/Method - asp.net-mvc

I want to get User's Location based on IP. When user enters website
I used to do it with XMLHTTPREquest in classic asp
how to do it with .net MVC.
I am new to .net

A combination of WebClient and JavaScriptSerializer classes could help you. As always start by defining a class that will represent your model:
public class LocationResult
{
public string Ip { get; set; }
public string Status { get; set; }
public string CountryCode { get; set; }
public string CountryName { get; set; }
public string RegionCode { get; set; }
public string RegionName { get; set; }
public string City { get; set; }
public string ZipPostalCode { get; set; }
public float Latitude { get; set; }
public float Longitude { get; set; }
}
and then call the service and deserialize the JSON result back to your model:
public LocationResult GetLocationInfo(string ip)
{
using (var client = new WebClient())
{
// query the online service provider and fetch the JSON
var json = client.DownloadString(
"http://ipinfodb.com/ip_query.php?ip=" + ip +
"&output=json&timezone=false"
);
// use the JavaScriptSerializer to deserialize the JSON
// result back to a LocationResult
var serializer = new JavaScriptSerializer();
return serializer.Deserialize<LocationResult>(json);
}
}

Related

Why Web Api include properties in response that are not projected

I have a view model
public class MyViewModel
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Position { get; set; }
public string Email { get; set; }
public string Office { get; set; }
public DateTime? StartDate { get; set; }
public int? Age { get; set; }
public int? Salary { get; set; }
public int? Extn { get; set; }
}
And I am doing projection on my entity
public List<ViewModel.StaffViewModel> GetAll()
{
var context = new GistDemoDbEntities();
var model = context.Staff
.Select(s => new ViewModel.StaffViewModel
{
FirstName = s.FirstName,
LastName = s.LastName,
Position = s.Position,
Salary = s.Salary
}).ToList();
return model;
}
And use Web Api to return back as json, but in reponse I found out it includes other properties as well that define in the View Model with vlaue null. I only want to have those properties that I need in reponse, how is it possible?
You can either:
Remove them from your ViewModel, a view model should only conta9in
what you intend to use anyway.
or
Use [JsonIgnore] on your properties to prevent JSON.Net from mapping
them.
Json Ignore is an attribute, look here;
http://james.newtonking.com/json/help/index.html?topic=html/SerializationAttributes.htm

Need to deserialize a nested json array to server side array

I have an array nested in an object in a JSON string which I need deserialized at the server:
var orderStatus = {"auth": "xxxx", "resourceType": "order.status", "idSet": "2980", "lifecycleEvent": "modified", "objects": { "orders": [ { "id": "2980", "statusId": "6" } ] }
I use Robert Koritnik's plugin like this:
$.ajax({url: "receiveJson", type: "POST", data: $.toDictionary(orderStatus) });
My .net class file is:
public class orders
{
public string Id { get; set; }
public string statusId { get; set; }
}
public class objects
{
public orders orders { get; set; }
}
public class OrderStatus
{
public string clientName { get; set; }
public string source { get; set; }
public string auth { get; set; }
public string resourceType { get; set; }
public string idSet { get; set; }
public string lifecycleEvent { get; set; }
public objects objects { get; set; }
}
my controller code is:
public JsonResult receiveJson(OrderStatus orderStatus)
So the orders object is the array. It works up to creating orders as an object but id and status id in the orders object are null.
I have no control over the JSON I will receive, it has to be in this format.
I am new to JSON and .NET MVC. Don't know how to specify server side orders object as an array.
Fixed it by slightly amending my server side classes:
public class order
{
public string Id { get; set; }
public string statusId { get; set; }
}
public class objects
{
public List<order> orders { get; set; }
}
public class OrderStatus
{
public string clientName { get; set; }
public string source { get; set; }
public string auth { get; set; }
public string resourceType { get; set; }
public string idSet { get; set; }
public string lifecycleEvent { get; set; }
public objects objects { get; set; }
}
So the "orders" class has been changed to "order". "objects.orders" property is amended to be a list.
Now the jsondata is deserialized all the way down.

MVC 4 Web API NullException Error (Noobie)

I'm working on my first MVC 4 app, following the MVC First Web API Tutorial on Asp.net. I've left the names the same, but changed the model and controller code. Here's my model:
public class Product
{
public string SID { get; set; }
public string name { get; set; }
public string givenName { get; set; }
public string sn { get; set; }
public string mail { get; set; }
public string telephoneNumber { get; set; }
public string mobile { get; set; }
public string otherMobile { get; set; }
public string title { get; set; }
public string Manager { get; set; }
public DateTime whenChanged { get; set; }
}
public class ProductModel
{
public ProductModel()
{
ProductList = new List<Product>();
}
public IList<Product> ProductList { get; set; }
}
And here's my APIcontroller:
public class ProductsController : ApiController
{
ProductModel products = new ProductModel();
public IEnumerable<Product> GetAD()
{
DirectoryEntry domainRoot = new DirectoryEntry(LDAP_server);
DirectorySearcher searcher = new DirectorySearcher(searchStr);
SearchResultCollection results = searcher.FindAll();
foreach (SearchResult srchResult in results)
{
DirectoryEntry dirEntry = srchResult.GetDirectoryEntry();
if (dirEntry.Properties["givenName"].Value != null && dirEntry.Properties["sn"].Value != null && !dirEntry.Parent.Name.Contains("Terminated"))
{
products.ProductList.Add(new Product()
{
SID = dirEntry.Properties["sid"].Value.ToString(),
name = dirEntry.Properties["name"].Value.ToString(),
givenName = dirEntry.Properties["givenName"].Value.ToString(),
sn = dirEntry.Properties["sn"].Value.ToString(),
mail = dirEntry.Properties["mail"].Value.ToString(),
telephoneNumber = dirEntry.Properties["telephoneNumber"].Value.ToString(),
mobile = dirEntry.Properties["mobile"].Value.ToString(),
otherMobile = dirEntry.Properties["otherMobile"].Value.ToString(),
title = dirEntry.Properties["title"].Value.ToString(),
Manager = dirEntry.Properties["Manager"].Value.ToString(),
whenChanged = Convert.ToDateTime(dirEntry.Properties["whenChanged"].Value.ToString()),
});
}
}
return products.ProductList;
}
}
I'm getting the NullException on 'products.ProductList.Add(new Product()', am I missing something simple? Please forgive my coding, as I'm just trying to get this up and running, thanks.
the problem mostly likely is dealing with dirEntry, not Web API itself. rather than introduce LDAP into this, just create a bunch of dummy products to return.
FYI... there is also a memory leak issue with the use of LDAP objects. They need to be properly disposed of, both along the happy path and if an exception is thrown.
I'm an idiot. 'sid' is not the correct property name from AD, it is 'objectSid', thus always returning a null. I knew it was something simple.

PagedList in MVC3 with IQueryable

I can't understand what i'm doing wrong. Every time I'm getting this error:
The entity or complex type 'BusinessLogic.CompanyWithDivisionCount' cannot be constructed in a LINQ to Entities query.
I need to get info from 'Company' table and divisions count of each company from 'Division' table, and then make PagedList. Here is my 'Company' table:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel.DataAnnotations;
using BusinessLogic.Services;
using BusinessLogic.Models.ValidationAttributes;
namespace BusinessLogic.Models
{
public class Company
{
public Company()
{
Country = "US";
Status = true;
}
public int Id { get; set; }
[Required]
[UniqueCompanyName]
public string Name { get; set; }
public string Street { get; set; }
public string City { get; set; }
public string State { get; set; }
public int Zip { get; set; }
public string Country { get; set; }
public string ContactInfo { get; set; }
[Required]
public DateTime EffectiveDate { get; set; }
public DateTime TerminationDate { get; set; }
public bool Status { get; set; }
[Required]
public string URL { get; set; }
public string EAP { get; set; }
public string EAPCredentials { get; set; }
public string BrandingColors { get; set; }
public string Comments { get; set; }
}
}
Here is my domain model:
public class Company
{
public Company()
{
Country = "US";
Status = true;
}
public int Id { get; set; }
[Required]
[UniqueCompanyName]
public string Name { get; set; }
public string Street { get; set; }
public string City { get; set; }
public string State { get; set; }
public int Zip { get; set; }
public string Country { get; set; }
public string ContactInfo { get; set; }
[Required]
public DateTime EffectiveDate { get; set; }
public DateTime TerminationDate { get; set; }
public bool Status { get; set; }
[Required]
public string URL { get; set; }
public string EAP { get; set; }
public string EAPCredentials { get; set; }
public string BrandingColors { get; set; }
public string Comments { get; set; }
}
public class CompanyWithDivisionCount: Company // I'm using this
{
public int DivisionCount { get; set; }
}
Here is my controller:
public ActionResult CompaniesList(int? page)
{
var pageNumber = page ?? 1;
var companies = companyService.GetCompaniesWithDivisionsCount2();
var model = companies.ToPagedList(pageNumber, PageSize);
return View(model);
}
And here is my service part:
public IQueryable<CompanyWithDivisionCount> GetCompaniesWithDivisionsCount2()
{
return (from c in dataContext.Companies.AsQueryable()
select new CompanyWithDivisionCount
{
Id = c.Id,
Name = c.Name,
Status = c.Status,
EffectiveDate = c.EffectiveDate,
URL = c.URL,
EAP = c.EAP,
EAPCredentials = c.EAPCredentials,
Comments = c.Comments,
DivisionCount = (int)dataContext.Divisions.Where(b => b.CompanyName == c.Name).Count()
});
}
}
Thanks for help!!!
Creator of PagedList here. This has nothing to do with PagedList, but rather is an Entity Framework issue (I'm no expert on Entity Framework, so can't help you there). To confirm that this is true, write a unit test along the following lines:
[Test]
public void ShouldNotThrowAnException()
{
//arrange
var companies = companyService.GetCompaniesWithDivisionsCount2();
//act
var result = companies.ToList();
//assert
//if this line is reached, we win! no exception on call to .ToList()
}
I would consider changing you data model if possible so that instead of relating Companies to Divisions by name strings, instead use a properly maintained foreign key relationship between the two objects (Divisions should contain a CompanyID foreign key). This has a number of benefits (including performance and data integrity) and will almost certainly make your life easier moving forward if you need to make further changes to you app (or if any company ever decides that it may re-brand it's name).
If you create a proper foreign key relationship then your domain model could look like
public class Company
{
...
public virtual ICollection<Division> Divisions{ get; set; }
public int DivisionCount
{
get
{
return this.Divisions.Count()
}
}
...
}

How can I handle large JSON input from Postmark in my MVC application?

This is related to this question, but in this case it's not something I am returning but rather the model binding. I am using Postmark to handle incoming emails, which posts to a page with a JSON payload.
I have a model as below and an action that takes in this JSON payload (posted with application/json) and processes it.
public class EmailModel
{
public IDictionary<string, string> Headers { get; set; }
public string From { get; set; }
public string Cc { get; set; }
public string HtmlBody { get; set; }
public string TextBody { get; set; }
public string ReplyTo { get; set; }
public string Tag { get; set; }
public string To { get; set; }
public string MessageID { get; set; }
public string MailboxHash { get; set; }
public string Subject { get; set; }
public List<Attachment> Attachments { get; set; }
}
public class Attachment
{
public string Content { get; set; }
public int ContentLength { get; set; }
public string ContentType { get; set; }
public string Name { get; set; }
}
This works fine for small attachments, but for anything that exceeds the default maxJsonLength property causes an error in deserialization. ("Error during serialization or deserialization using the JSON JavaScriptSerializer. The length of the string exceeds the value set on the maxJsonLength property.") Because I want to accept image attachments, this means most images fail.
I've tried updating the web.config, but as per those other threads, this doesn't help for MVC controllers. I figure I can probably do what was mentioned in a custom IModelBinder, but I'm struggling with how to intercept the deserialization. (In other words, it still fails because the deserialization has happened already).
Any suggestions? I'm sure it's just something stupid that I'm missing....
You could write a custom JsonValueProviderFactory that uses Json.NET:
public sealed class JsonDotNetValueProviderFactory : ValueProviderFactory
{
public override IValueProvider GetValueProvider(ControllerContext controllerContext)
{
if (controllerContext == null)
throw new ArgumentNullException("controllerContext");
if (!controllerContext.HttpContext.Request.ContentType.StartsWith("application/json", StringComparison.OrdinalIgnoreCase))
return null;
var reader = new StreamReader(controllerContext.HttpContext.Request.InputStream);
var bodyText = reader.ReadToEnd();
return String.IsNullOrEmpty(bodyText) ? null : new DictionaryValueProvider<object>(JsonConvert.DeserializeObject<ExpandoObject>(bodyText, new ExpandoObjectConverter()) , CultureInfo.CurrentCulture);
}
}
and in your Application_Start:
ValueProviderFactories.Factories.Remove(ValueProviderFactories.Factories.OfType<JsonValueProviderFactory>().FirstOrDefault());
ValueProviderFactories.Factories.Add(new JsonDotNetValueProviderFactory());

Resources