ASP.NET Web API upload image to SQL Server database - c#

I'm writing an article API with image and I've been following this tutorial about uploading file in ASP.NET web API, the Title and Content are saved to database as intended.
The problem here is, the images that I post are saved to my local folder but the fields Filename, Filepath, Filelength, and Filecreatedtime aren't saved to database.
Posting article to database with postman:
The ImageFolder:
GET index:
The database:
here's my Article model:
namespace Wwf_Article.Models
{
using System;
using System.Collections.Generic;
public partial class Article
{
public int ID { get; set; }
public string Title { get; set; }
public string Content { get; set; }
public string FileName { get; set; }
public string FilePath { get; set; }
public float FileLength { get; set; }
public DateTime FileCreatedTime { get;
}
}
and here's my POST controller
[Mime]
public async Task<IHttpActionResult> Post()
{
var fileuploadPath = HttpContext.Current.Server.MapPath("~/ImageFolder");
var multiFormDataStreamProvider = new MultiFileUploadProvider(fileuploadPath);
await Request.Content.ReadAsMultipartAsync(multiFormDataStreamProvider);
string uploadingFileName = multiFormDataStreamProvider.FileData.Select(x => x.LocalFileName).FirstOrDefault();
Article article = new Article
{
Title = HttpContext.Current.Request.Form["Title"],
Content = HttpContext.Current.Request.Form["Content"],
//these four lines below aren't saved to DB
FilePath = uploadingFileName,
FileName = Path.GetFileName(uploadingFileName),
FileLength = new FileInfo(uploadingFileName).Length,
FileCreatedTime = DateTime.Now
};
db.Articles.Add(article);
db.SaveChanges();
return Ok();
}
Any idea how to fix this problem?

Are the 4 four lines below as you mentionned part of your Article model class?
I mean (FilePath, FileName, FileLength and FileCreatedTime)

1- If yes, i think you can use a stored procedure to achieve your request like the following
CREATE PROC spInsertArticle
#Title varchar(100),
#Content varchar(100),
#FileName varchar(500),
#FilePath varchar(500),
#FileLength varchar(500)
AS
Insert Into ArticleTable(Title,Content,FileName,
FilePath,FileLength,FileContentTime)
Values (#Title,#Content,#FileName,
#FilePath,#FileLength,GetDate())
2-Go back to your api project and create a model class called ArticleModel:
public class ArticleModel
{
public string Title {get; set; }
public string Content {get; set; }
public string FileName {get; set; }
public string FilePath {get; set; }
public string FileLength {get; set; }
}
3-Create an api post method in the ArticleController
[Route("api/ArticleController/PostArticle")]
public HttpResponseMessage PostArticle(ArticleModel obj)
{
if (ModelState.IsValid)
{
try
{
string PhotoPath = Convert.ToString(ConfigurationManager.AppSettings["ImagePath"]);
ArticleModel newObj = new ArticleModel();
newObj.Title = obj.Title ;
newObj.Content = obj.Content;
newObj.FileName = obj.FileName;
newObj.FilePath = obj.FilePath;
newObjl.FileLength = obj.FileLength;
if (String.IsNullOrEmpty(newObj.Content))
{
}
else
{
string startingFilePath = PhotoPath;
string FilePath = SaveImage(newObj.Content, startingFilePath, newObj.FileName);
FileInfo fInfo = new FileInfo(FilePath);
newObj.Content = fInfo.Name;
}
ArticleEntities context = new ArticleEntities();
var newArticle = context.spInsertArticle(newObj.Title, newObj.Content,
newObj.FileName, newObj.FilePath, newObj.FileLength);
return Request.CreateResponse(HttpStatusCode.Created, newArticle);
}
catch (Exception ex)
{
return Request.CreateResponse(HttpStatusCode.InternalServerError, ex);
}
}
else
{
return Request.CreateResponse(HttpStatusCode.BadRequest, ModelState);
}
}
4-And finally create the SaveImage method mentionned in the PostArticle method
private string SaveImage(string base64, string FilePath, string ImageName)
{
//Get the file type to save in
var FilePathWithExtension = "";
string localBase64 = "";
if (base64.Contains("data:image/jpeg;base64,"))
{
FilePathWithExtension = FilePath + ImageName + ".jpg";
localBase64 = base64.Replace("data:image/jpeg;base64,", "");
}
else if (base64.Contains("data:image/png;base64,"))
{
FilePathWithExtension = FilePath + ImageName + ".png";
localBase64 = base64.Replace("data:image/png;base64,", "");
}
else if (base64.Contains("data:image/bmp;base64"))
{
FilePathWithExtension = FilePath + ImageName + ".bmp";
localBase64 = base64.Replace("data:image/bmp;base64", "");
}
else if (base64.Contains("data:application/msword;base64,"))
{
FilePathWithExtension = FilePath + ImageName + ".doc";
localBase64 = base64.Replace("data:application/msword;base64,", "");
}
else if (base64.Contains("data:application/vnd.openxmlformats-officedocument.wordprocessingml.document;base64,"))
{
FilePathWithExtension = FilePath + ImageName + ".docx";
localBase64 = base64.Replace("data:application/vnd.openxmlformats-officedocument.wordprocessingml.document;base64,", "");
}
else if (base64.Contains("data:application/pdf;base64,"))
{
FilePathWithExtension = FilePath + ImageName + ".pdf";
localBase64 = base64.Replace("data:application/pdf;base64,", "");
}
using (MemoryStream ms = new MemoryStream(Convert.FromBase64String(localBase64)))
{
using (FileStream fs = new FileStream(FilePathWithExtension, FileMode.Create, FileAccess.Write))
{
//Create the specified directory if it does not exist
var photofolder = System.IO.Path.GetDirectoryName(FilePathWithExtension);
if (!Directory.Exists(photofolder))
{
Directory.CreateDirectory(photofolder);
}
ms.WriteTo(fs);
fs.Close();
ms.Close();
}
}
return FilePathWithExtension;
}
5-Try this in either Postman or swagger and it will work for you. I am available for any discussion

First of all, create a Generic interface repo class
public interface IRepository<T> where T : class
{
T GetById(int id);
void Add(T entity);
}

Create a class that will implement the interface
public class EFRepository<T> : IRepository<T> where T : class
{
public EFRepository(PayrollcshrnewEntities dbContext)
{
if (dbContext == null)
throw new ArgumentNullException("dbContext");
DbContext = dbContext;
DbSet = DbContext.Set<T>();
}
protected ArticleEntities DbContext { get; set; }
protected DbSet<T> DbSet { get; set; }
public virtual T GetById(int id)
{
return DbSet.Find(id);
}
public virtual void Add(T entity)
{
DbEntityEntry dbEntityEntry = DbContext.Entry(entity);
if (dbEntityEntry.State != EntityState.Detached)
{
dbEntityEntry.State = EntityState.Added;
}
else
{
DbSet.Add(entity);
}
}
}

For some reason after I delete the edmx and recreate the EF designer table with ADO, the POST controller works.
It turns out there's missing fields in the edmx diagram.
Thanks for all the help anyway, guys

Related

JsonConvert.DeserializeObject() throwing System.ArgumentNullException: 'Path cannot be null. Parameter name: path' exception. Why?

My class structure is as follows:
class AppDetails
{
public String companyName { get; set; }
public String applicationName { get; set; }
public String version { get; set; }
public List<File_> fileObjectList { get; set; }
public AppDetails(String cName, String aName, String v)
{
companyName = cName;
applicationName = aName;
version = v;
}
}
class File_
{
public String filePath { get; set; }
public FileRecord fileRecord { get; set; }
public File_(String parent_, String filepath_, Boolean Ignored)
{
filePath = filepath_;
fileRecord = new FileRecord(parent_ + filePath, Ignored);
}
}
class FileRecord
{
public Boolean ignored { get; set; }
public String MD5Checksum { get; set; }
public int version { get; set; }
public FileRecord(String filePath, Boolean ignored_)
{
ignored = ignored_;
if (ignored)
{
MD5Checksum = null;
}
else
{
MD5Checksum = CalculateMD5(filePath);
version = 0;
}
}
static string CalculateMD5(string filePath)
{
var md5 = MD5.Create();
var stream = File.OpenRead(filePath);
var hash = md5.ComputeHash((System.IO.Stream)stream);
return BitConverter.ToString(hash).Replace("-", "").ToLowerInvariant();
}
}
I generated Json file using these classes. But when I try to initialize an object with the said JSON file, it throws System.ArgumentNullException: 'Path cannot be null. Parameter name: path' exception.
This is the function that is supposed to return the object.
AppDetails ReadJsonFile()
{
using (StreamReader r = File.OpenText(parent + "\\AllFilesList.json"))
{
string json = r.ReadToEnd();
var result = JsonConvert.DeserializeObject<AppDetails>(json);
return result;
}
}
I tried generating the classes from JSON using online class generators and it matches my class structure. Exception is thrown on this line:
var result = JsonConvert.DeserializeObject<AppDetails>(json);
Json string is getting loaded with the content from the file just fine(as can be seen from the watch). I couldn't find anything about Path issues related to JsonConvert.DeserializeObject. Most previous questions seems to be related to value errors.
EDIT: Serialization Code
void JsonWriter(AppDetails appDetails, String filename)
{
string path = parent + "\\" + filename + ".json";
File.Delete(path);
string json = JsonConvert.SerializeObject(appDetails);
using (var tw = new StreamWriter(path, true))
{
tw.WriteLine(json.ToString());
tw.Close();
}
}
Sample Json File:
{"companyName":"Home","applicationName":"Test","version":"V5.0.1","fileObjectList":[{"filePath":"\\bug-tracker.exe","fileRecord":{"ignored":false,"MD5Checksum":"a5254a813a040b429f2288df737a8b9f","version":0}},{"filePath":"\\bug-tracker.exe.config","fileRecord":{"ignored":false,"MD5Checksum":"e5c3e9137dc8fadb57dfc27b0ba6855c","version":0}},{"filePath":"\\bug-tracker.pdb","fileRecord":{"ignored":false,"MD5Checksum":"9a9dfda29dcaacae82cba7bd7aa97ffa","version":0}},{"filePath":"\\Caliburn.Micro.dll","fileRecord":{"ignored":false,"MD5Checksum":"aa5f96c02b08d9b33322f3024058dd91","version":0}},{"filePath":"\\Caliburn.Micro.Platform.Core.dll","fileRecord":{"ignored":false,"MD5Checksum":"ab7867bd44b59879a59b5cb968e15668","version":0}},{"filePath":"\\Caliburn.Micro.Platform.Core.xml","fileRecord":{"ignored":false,"MD5Checksum":"cdfcbbf70a9a62b92e82a953ab9e7e30","version":0}},{"filePath":"\\Caliburn.Micro.Platform.dll","fileRecord":{"ignored":false,"MD5Checksum":"a52bdecbc1b7625cb13c9385fad4231b","version":0}},{"filePath":"\\Caliburn.Micro.Platform.xml","fileRecord":{"ignored":false,"MD5Checksum":"09f258a3aeca7285355d82a66dda2176","version":0}},{"filePath":"\\Caliburn.Micro.xml","fileRecord":{"ignored":false,"MD5Checksum":"c87ec582a4bfcf2e79e517c689441def","version":0}},{"filePath":"\\MaterialDesignColors.dll","fileRecord":{"ignored":false,"MD5Checksum":"ad729352a9088b889cc0c4dc7542dcb6","version":0}},{"filePath":"\\MaterialDesignColors.pdb","fileRecord":{"ignored":false,"MD5Checksum":"7ba70b23e22db9ac155e190860d9a5ec","version":0}},{"filePath":"\\MaterialDesignThemes.Wpf.dll","fileRecord":{"ignored":false,"MD5Checksum":"e4c790d3af41620dc5ad513ae7fcadac","version":0}},{"filePath":"\\MaterialDesignThemes.Wpf.pdb","fileRecord":{"ignored":false,"MD5Checksum":"f8113c8ea54896b8150db8e7ebd506ef","version":0}},{"filePath":"\\MaterialDesignThemes.Wpf.xml","fileRecord":{"ignored":false,"MD5Checksum":"49717f8130b7529ee51fb6bc13f79aa4","version":0}},{"filePath":"\\ShowMeTheXAML.dll","fileRecord":{"ignored":false,"MD5Checksum":"040b9e80820553a55f13ac19c2036367","version":0}},{"filePath":"\\System.Windows.Interactivity.dll","fileRecord":{"ignored":false,"MD5Checksum":"580244bc805220253a87196913eb3e5e","version":0}}]}
Edit 2: Json String from watch
"{\"companyName\":\"Home\",\"applicationName\":\"Test\",\"version\":\"V5.0.1\",\"fileObjectList\":[{\"filePath\":\"\\\\bug-tracker.exe\",\"fileRecord\":{\"ignored\":false,\"MD5Checksum\":\"a5254a813a040b429f2288df737a8b9f\",\"version\":0}},{\"filePath\":\"\\\\bug-tracker.exe.config\",\"fileRecord\":{\"ignored\":false,\"MD5Checksum\":\"e5c3e9137dc8fadb57dfc27b0ba6855c\",\"version\":0}},{\"filePath\":\"\\\\bug-tracker.pdb\",\"fileRecord\":{\"ignored\":false,\"MD5Checksum\":\"9a9dfda29dcaacae82cba7bd7aa97ffa\",\"version\":0}},{\"filePath\":\"\\\\Caliburn.Micro.dll\",\"fileRecord\":{\"ignored\":false,\"MD5Checksum\":\"aa5f96c02b08d9b33322f3024058dd91\",\"version\":0}},{\"filePath\":\"\\\\Caliburn.Micro.Platform.Core.dll\",\"fileRecord\":{\"ignored\":false,\"MD5Checksum\":\"ab7867bd44b59879a59b5cb968e15668\",\"version\":0}},{\"filePath\":\"\\\\Caliburn.Micro.Platform.Core.xml\",\"fileRecord\":{\"ignored\":false,\"MD5Checksum\":\"cdfcbbf70a9a62b92e82a953ab9e7e30\",\"version\":0}},{\"filePath\":\"\\\\Caliburn.Micro.Platform.dll\",\"fileRecord\":{\"ignored\":false,\"MD5Checksum\":\"a52bdecbc1b7625cb13c9385fad4231b\",\"version\":0}},{\"filePath\":\"\\\\Caliburn.Micro.Platform.xml\",\"fileRecord\":{\"ignored\":false,\"MD5Checksum\":\"09f258a3aeca7285355d82a66dda2176\",\"version\":0}},{\"filePath\":\"\\\\Caliburn.Micro.xml\",\"fileRecord\":{\"ignored\":false,\"MD5Checksum\":\"c87ec582a4bfcf2e79e517c689441def\",\"version\":0}},{\"filePath\":\"\\\\MaterialDesignColors.dll\",\"fileRecord\":{\"ignored\":false,\"MD5Checksum\":\"ad729352a9088b889cc0c4dc7542dcb6\",\"version\":0}},{\"filePath\":\"\\\\MaterialDesignColors.pdb\",\"fileRecord\":{\"ignored\":false,\"MD5Checksum\":\"7ba70b23e22db9ac155e190860d9a5ec\",\"version\":0}},{\"filePath\":\"\\\\MaterialDesignThemes.Wpf.dll\",\"fileRecord\":{\"ignored\":false,\"MD5Checksum\":\"e4c790d3af41620dc5ad513ae7fcadac\",\"version\":0}},{\"filePath\":\"\\\\MaterialDesignThemes.Wpf.pdb\",\"fileRecord\":{\"ignored\":false,\"MD5Checksum\":\"f8113c8ea54896b8150db8e7ebd506ef\",\"version\":0}},{\"filePath\":\"\\\\MaterialDesignThemes.Wpf.xml\",\"fileRecord\":{\"ignored\":false,\"MD5Checksum\":\"49717f8130b7529ee51fb6bc13f79aa4\",\"version\":0}},{\"filePath\":\"\\\\ShowMeTheXAML.dll\",\"fileRecord\":{\"ignored\":false,\"MD5Checksum\":\"040b9e80820553a55f13ac19c2036367\",\"version\":0}},{\"filePath\":\"\\\\System.Windows.Interactivity.dll\",\"fileRecord\":{\"ignored\":false,\"MD5Checksum\":\"580244bc805220253a87196913eb3e5e\",\"version\":0}}]}\r\n"
The actual issue is that you have the parameters in your constructor:
public FileRecord(String filePath, Boolean ignored_)
And JsonConvert puts there default values (null, false) which triggers the code:
else
{
MD5Checksum = CalculateMD5(filePath);
version = 0;
}
Which in its turn tries to read from a file using null path parameter:
static string CalculateMD5(string filePath)
{
var md5 = MD5.Create();
var stream = File.OpenRead(filePath); // <- HERE!!!!
var hash = md5.ComputeHash((System.IO.Stream)stream);
return BitConverter.ToString(hash).Replace("-", "").ToLowerInvariant();
}
I see there two solutions
Create parameterless constructors where init everything as you need or call the constructor with parameters using :this() with defaults:
public FileRecord() : this(null, true)
{
}
Rename properties to match parameter names, like:
public bool Ignored { get; set; }
public FileRecord(string filePath, bool ignored)
{
this.Ingnoerd = ignored;
....
}

How to update a record in database in Entity Framework?

I'm using c# mvc with EF and i'm building a website. When i'm updating a table with new values it gives the following error.
{"Violation of PRIMARY KEY constraint 'PK_Table_1_1'. Cannot insert duplicate key in object 'dbo.User'. The duplicate key value is (shan#gmail.com).\r\nThe statement has been terminated."}
Here is my design of the table.
Here is my controller file
[HttpPost]
public ActionResult Manage(ManageViewModel manageviewmodel)
{
TheFoodyContext db = new TheFoodyContext();
string UserEmail = Session["UserEmail"].ToString();
User user_to_update = db.Users.Find(UserEmail);
if (ModelState.IsValid)
{
try
{
HttpPostedFileBase photo = Request.Files["photo"];
if (photo != null && photo.ContentLength > 0)
{
var path = "";
var fileName = Path.GetFileName(photo.FileName);
var extension = Path.GetExtension(photo.FileName);
var allowedExtensions = new[] {".Jpg", ".png", ".jpg", "jpeg"};
if (allowedExtensions.Contains(extension))
{
string name = Path.GetFileNameWithoutExtension(fileName);
string myfile = name + "_" + UserEmail + extension;
path= Path.Combine(Server.MapPath("~/Img"), myfile);
photo.SaveAs(path);
user_to_update.photo = myfile;
}
else
{
ViewBag.message = "Please choose only Image file";
}
user_to_update.email = UserEmail;
user_to_update.fname = manageviewmodel.FirstName;
user_to_update.lname = manageviewmodel.LastName;
user_to_update.phone = manageviewmodel.Phone;
user_to_update.address = manageviewmodel.Address;
user_to_update.city = manageviewmodel.City;
user_to_update.postcode = Convert.ToDecimal(manageviewmodel.PostCode);
user_to_update.district = manageviewmodel.District;
user_to_update.user_type = manageviewmodel.UserType;
user_to_update.status = manageviewmodel.Status;
user_to_update.photo = path;
db.Users.Add(user_to_update);
db.SaveChanges();
Session["UserEmail"] = UserEmail;
Session["FirstName"] = manageviewmodel.FirstName;
Session["LastName"] = manageviewmodel.LastName;
Session["Address"] = manageviewmodel.Address;
Session["City"] = manageviewmodel.City;
Session["PostCode"] = manageviewmodel.PostCode;
Session["District"] = manageviewmodel.District;
Session["UserType"] = manageviewmodel.UserType;
Session["Status"] = manageviewmodel.Status;
Session["Phone"] = manageviewmodel.Phone;
return RedirectToAction("Manage");
}
}
catch (Exception ex)
{
return View(ex.Message);
}
return View(manageviewmodel);
}
return View(manageviewmodel);
}
Here is my Model file
public class ManageViewModel
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string Email { get; set; }
public string Phone { get; set; }
public string photo { get; set; }
public string Address { get; set; }
public string City { get; set; }
public int PostCode { get; set; }
public string District { get; set; }
public string UserType { get; set; }
public string Status { get; set; }
}
You don't need to add the user again (it already exists and EF tracks changes), simply call SaveChanges and you are done.
Just remove this line:
db.Users.Add(user_to_update);
and it should work (unless there are more errors).

WebImage helper not creating correct path to image?

My problem is with the following piece of code. I have built WebPages app where this chunk of code works perfectly, however, in my MVC5 app it copies only the local path from my PC to MSSQL database, without a GUID even. The piece of code is:
CONTROLLER:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit([Bind(Include="productId,categoryId,brandId,Name,Price,ProductImg")] Product product)
{
if (ModelState.IsValid)
{
WebImage photo = null;
var newFileName = "";
var imagePath = "";
//RIJEŠITI NESTED IF
//zašto ne prihvaća HttpPostedFileBase tip??
photo = WebImage.GetImageFromRequest();
if (photo != null)
{
newFileName = Guid.NewGuid().ToString() + "_" +
Path.GetFileName(photo.FileName);
imagePath = #"Content\Images\" + newFileName;
photo.Save(#"~\" + imagePath);
product.ProductImg = #"~\" + imagePath;
}
try
{
db.Entry(product).State = System.Data.Entity.EntityState.Modified;
db.SaveChanges();
}
catch (DbUpdateConcurrencyException)
{
var objContext = ((IObjectContextAdapter)db).ObjectContext;
objContext.Refresh(System.Data.Entity.Core.Objects.RefreshMode.ClientWins, product);
}
return RedirectToAction("Index");
}
}
MODEL:
public class Product
{
[ScaffoldColumn(false)]
public int productId { get; set; }
[DisplayName("Category")]
public int categoryId { get; set; }
[DisplayName("Brand")]
public int brandId { get; set; }
[DisplayName("Product Name")]
[Required(ErrorMessage = "Product Name is mandatory")]
[StringLength(160)]
public string Name { get; set; }
[Required(ErrorMessage = "Price is required")]
[Range(0.01, 7000.00,
ErrorMessage = "Price must be between 0.01 and 7000.00")]
public decimal Price { get; set; }
[DisplayName("Product Image")]
[StringLength(1024)]
public string ProductImg { get; set; }
public virtual Category Category { get; set; }
public virtual Brand Brand { get; set; }
public virtual List<OrderDetail> OrderDetails { get; set; }
}
Also how do I prevent this code from writing NULL to database in case that the user doesn't want to change the image?
Don't trust Filename provided by browser: some browsers send the full path others send only the file name. So you'd vetter use the following code to upload your picture/file
//-----
String path = Server.MapPath("~/content/public");
if (Request.Files != null && Request.Files.Count > 0)
{
String fileExtension = System.IO.Path.GetExtension(Request.Files[0].FileName).ToLower();
List<string> allowedExtensions = new List<string>(){".gif", ".png", ".jpeg", ".jpg" };
if (allowedExtensions.Contains(fileExtension))
{
string fileName = Guid.NewGuid().ToString();
Request.Files[0].SaveAs(path + fileName);
product.ProductImg = fileName ;
}
}
///------
and to display this image, use a simple img tag as follows
#{string imageUrl=Url.Content("~/content/public/"+Model.ProductImg); }
<img src="#imageUrl" alt=""/>
This can provide you with a guid...or you'll need to remove / or \ as follows
string fileName = Guid.NewGuid().ToString();
fileName +="_"+Request.Files[0].FileName.Split(new char[]{'/','\'}).ToList().LastOrDefault();

Trying to get right JSON format from a asp.net Web API post

I need my response to look like this (JSON array inside the object):
{"files":[
{
"name":"3992wp_ss_20130215_0001.jpg","size":102,"url":"/Files/3992wp_ss_20130215_0001.jpg","thumbnail_url":"","de lete_url":"/Files/3992wp_ss_20130215_0001.jpg","delete_type":"DELETE"
}
]}
But I'm getting this (JSON array around the object):
[{"files":
{"name":"3992wp_ss_20130215_0001.jpg","size":102,"url":"/Files/3992wp_ss_20130215_0001.jpg","thumbnail_url":"","delete_url":"/Files/3992wp_ss_20130215_0001.jpg","delete_type":"DELETE"}}
]
Here is my code:
public IEnumerable<allFiles> Post()
{
// read data
List<DocFile> files = new List<DocFile>();
DocFile file1 = new DocFile();
file1.name = _fileName;
file1.size = _lengh;
file1.url = "/Files/" + _fileName;
file1.thumbnail_url = "";
file1.delete_url = "/Files/" + _fileName;
file1.delete_type = "DELETE";
files.Add(file1);
allFiles fileCont = new allFiles();
fileCont.files = files;
return fileCont;
}
public class allFiles
{
public IEnumerable<DocFile> files { get; set; }
}
public class DocFile
{
public string name { get; set; }
public long size { get; set; }
public string url { get; set; }
public string thumbnail_url { get; set; }
public string delete_url { get; set; }
public string delete_type { get; set; }
}
I think your problem is in the return, try to return allFiles instance.
Something like:
public allFiles Post()
{
//read data
List<DocFile> files = new List<DocFile>();
DocFile file1 = new DocFile();
file1.name = _fileName;
file1.size = _lengh;
file1.url = "/Files/" + _fileName;
file1.thumbnail_url = "";
file1.delete_url = "/Files/" + _fileName;
file1.delete_type = "DELETE";
files.Add(file1);
allFiles fileCont = new allFiles();
fileCont.files = files;
return fileCont;
}

Get user location by IP address [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
We don’t allow questions seeking recommendations for books, tools, software libraries, and more. You can edit the question so it can be answered with facts and citations.
Closed 4 months ago.
The community reviewed whether to reopen this question 4 months ago and left it closed:
Original close reason(s) were not resolved
Improve this question
I have an ASP.NET website written in C#.
On this site I need to automatically show a start page based on the user's location.
Can I get name of user's city based on the IP address of the user ?
You need an IP-address-based reverse geocoding API... like the one from ipdata.co. I'm sure there are plenty of options available.
You may want to allow the user to override this, however. For example, they could be on a corporate VPN which makes the IP address look like it's in a different country.
Use http://ipinfo.io , You need to pay them if you make more than 1000 requests per day.
The code below requires the Json.NET package.
public static string GetUserCountryByIp(string ip)
{
IpInfo ipInfo = new IpInfo();
try
{
string info = new WebClient().DownloadString("http://ipinfo.io/" + ip);
ipInfo = JsonConvert.DeserializeObject<IpInfo>(info);
RegionInfo myRI1 = new RegionInfo(ipInfo.Country);
ipInfo.Country = myRI1.EnglishName;
}
catch (Exception)
{
ipInfo.Country = null;
}
return ipInfo.Country;
}
And the IpInfo Class I used:
public class IpInfo
{
[JsonProperty("ip")]
public string Ip { get; set; }
[JsonProperty("hostname")]
public string Hostname { get; set; }
[JsonProperty("city")]
public string City { get; set; }
[JsonProperty("region")]
public string Region { get; set; }
[JsonProperty("country")]
public string Country { get; set; }
[JsonProperty("loc")]
public string Loc { get; set; }
[JsonProperty("org")]
public string Org { get; set; }
[JsonProperty("postal")]
public string Postal { get; set; }
}
Following Code work for me.
Update:
As I am calling a free API request (json base ) IpStack.
public static string CityStateCountByIp(string IP)
{
//var url = "http://freegeoip.net/json/" + IP;
//var url = "http://freegeoip.net/json/" + IP;
string url = "http://api.ipstack.com/" + IP + "?access_key=[KEY]";
var request = System.Net.WebRequest.Create(url);
using (WebResponse wrs = request.GetResponse())
{
using (Stream stream = wrs.GetResponseStream())
{
using (StreamReader reader = new StreamReader(stream))
{
string json = reader.ReadToEnd();
var obj = JObject.Parse(json);
string City = (string)obj["city"];
string Country = (string)obj["region_name"];
string CountryCode = (string)obj["country_code"];
return (CountryCode + " - " + Country +"," + City);
}}}
return "";
}
Edit :
First, it was http://freegeoip.net/ now it's https://ipstack.com/ (and maybe now it's a paid service- Free Up to 10,000 request/month)
IPInfoDB has an API that you can call in order to find a location based on an IP address.
For "City Precision", you call it like this (you'll need to register to get a free API key):
http://api.ipinfodb.com/v2/ip_query.php?key=<your_api_key>&ip=74.125.45.100&timezone=false
Here's an example in both VB and C# that shows how to call the API.
I have tried using http://ipinfo.io and this JSON API works perfectly. First, you need to add the below mentioned namespaces:
using System.Linq;
using System.Web;
using System.Web.UI.WebControls;
using System.Net;
using System.IO;
using System.Xml;
using System.Collections.Specialized;
For localhost it will give dummy data as AU. You can try hardcoding your IP and get results:
namespace WebApplication4
{
public partial class WebForm1 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
string VisitorsIPAddr = string.Empty;
//Users IP Address.
if (HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"] != null)
{
//To get the IP address of the machine and not the proxy
VisitorsIPAddr = HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"].ToString();
}
else if (HttpContext.Current.Request.UserHostAddress.Length != 0)
{
VisitorsIPAddr = HttpContext.Current.Request.UserHostAddress;`enter code here`
}
string res = "http://ipinfo.io/" + VisitorsIPAddr + "/city";
string ipResponse = IPRequestHelper(res);
}
public string IPRequestHelper(string url)
{
string checkURL = url;
HttpWebRequest objRequest = (HttpWebRequest)WebRequest.Create(url);
HttpWebResponse objResponse = (HttpWebResponse)objRequest.GetResponse();
StreamReader responseStream = new StreamReader(objResponse.GetResponseStream());
string responseRead = responseStream.ReadToEnd();
responseRead = responseRead.Replace("\n", String.Empty);
responseStream.Close();
responseStream.Dispose();
return responseRead;
}
}
}
I was able to achieve this in ASP.NET MVC using the client IP address and freegeoip.net API. freegeoip.net is free and does not require any license.
Below is the sample code I used.
String UserIP = HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"];
if (string.IsNullOrEmpty(UserIP))
{
UserIP = HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"];
}
string url = "http://freegeoip.net/json/" + UserIP.ToString();
WebClient client = new WebClient();
string jsonstring = client.DownloadString(url);
dynamic dynObj = JsonConvert.DeserializeObject(jsonstring);
System.Web.HttpContext.Current.Session["UserCountryCode"] = dynObj.country_code;
You can go through this post for more details.Hope it helps!
Using the Request of following web site
http://ip-api.com/
Following is C# code for returning Country and Country Code
public string GetCountryByIP(string ipAddress)
{
string strReturnVal;
string ipResponse = IPRequestHelper("http://ip-api.com/xml/" + ipAddress);
//return ipResponse;
XmlDocument ipInfoXML = new XmlDocument();
ipInfoXML.LoadXml(ipResponse);
XmlNodeList responseXML = ipInfoXML.GetElementsByTagName("query");
NameValueCollection dataXML = new NameValueCollection();
dataXML.Add(responseXML.Item(0).ChildNodes[2].InnerText, responseXML.Item(0).ChildNodes[2].Value);
strReturnVal = responseXML.Item(0).ChildNodes[1].InnerText.ToString(); // Contry
strReturnVal += "(" +
responseXML.Item(0).ChildNodes[2].InnerText.ToString() + ")"; // Contry Code
return strReturnVal;
}
And following is Helper for requesting url.
public string IPRequestHelper(string url) {
HttpWebRequest objRequest = (HttpWebRequest)WebRequest.Create(url);
HttpWebResponse objResponse = (HttpWebResponse)objRequest.GetResponse();
StreamReader responseStream = new StreamReader(objResponse.GetResponseStream());
string responseRead = responseStream.ReadToEnd();
responseStream.Close();
responseStream.Dispose();
return responseRead;
}
What you need is called a "geo-IP database". Most of them cost some money (albeit not too expensive), especially fairly precise ones. One of the most widely used is MaxMind's database. They have a fairly good free version of IP-to-city database called GeoLity City - it has lots of restrictions, but if you can cope with that that would be probably your best choice, unless you have some money to spare for a subscription to more accurate product.
And, yeah, they do have a C# API to query geo-IP databases available.
You'll probably have to use an external API, most of which cost money.
I did find this though, seems to be free: http://hostip.info/use.html
Return country
static public string GetCountry()
{
return new WebClient().DownloadString("http://api.hostip.info/country.php");
}
Usage:
Console.WriteLine(GetCountry()); // will return short code for your country
Return info
static public string GetInfo()
{
return new WebClient().DownloadString("http://api.hostip.info/get_json.php");
}
Usage:
Console.WriteLine(GetInfo());
// Example:
// {
// "country_name":"COUNTRY NAME",
// "country_code":"COUNTRY CODE",
// "city":"City",
// "ip":"XX.XXX.XX.XXX"
// }
It's good sample for you:
public class IpProperties
{
public string Status { get; set; }
public string Country { get; set; }
public string CountryCode { get; set; }
public string Region { get; set; }
public string RegionName { get; set; }
public string City { get; set; }
public string Zip { get; set; }
public string Lat { get; set; }
public string Lon { get; set; }
public string TimeZone { get; set; }
public string ISP { get; set; }
public string ORG { get; set; }
public string AS { get; set; }
public string Query { get; set; }
}
public string IPRequestHelper(string url)
{
HttpWebRequest objRequest = (HttpWebRequest)WebRequest.Create(url);
HttpWebResponse objResponse = (HttpWebResponse)objRequest.GetResponse();
StreamReader responseStream = new StreamReader(objResponse.GetResponseStream());
string responseRead = responseStream.ReadToEnd();
responseStream.Close();
responseStream.Dispose();
return responseRead;
}
public IpProperties GetCountryByIP(string ipAddress)
{
string ipResponse = IPRequestHelper("http://ip-api.com/xml/" + ipAddress);
using (TextReader sr = new StringReader(ipResponse))
{
using (System.Data.DataSet dataBase = new System.Data.DataSet())
{
IpProperties ipProperties = new IpProperties();
dataBase.ReadXml(sr);
ipProperties.Status = dataBase.Tables[0].Rows[0][0].ToString();
ipProperties.Country = dataBase.Tables[0].Rows[0][1].ToString();
ipProperties.CountryCode = dataBase.Tables[0].Rows[0][2].ToString();
ipProperties.Region = dataBase.Tables[0].Rows[0][3].ToString();
ipProperties.RegionName = dataBase.Tables[0].Rows[0][4].ToString();
ipProperties.City = dataBase.Tables[0].Rows[0][5].ToString();
ipProperties.Zip = dataBase.Tables[0].Rows[0][6].ToString();
ipProperties.Lat = dataBase.Tables[0].Rows[0][7].ToString();
ipProperties.Lon = dataBase.Tables[0].Rows[0][8].ToString();
ipProperties.TimeZone = dataBase.Tables[0].Rows[0][9].ToString();
ipProperties.ISP = dataBase.Tables[0].Rows[0][10].ToString();
ipProperties.ORG = dataBase.Tables[0].Rows[0][11].ToString();
ipProperties.AS = dataBase.Tables[0].Rows[0][12].ToString();
ipProperties.Query = dataBase.Tables[0].Rows[0][13].ToString();
return ipProperties;
}
}
}
And test:
var ipResponse = GetCountryByIP("your ip address or domain name :)");
An Alternative to using an API is to use HTML 5 location Navigator to query the browser about the User location. I was looking for a similar approach as in the subject question but I found that HTML 5 Navigator works better and cheaper for my situation. Please consider that your scinario might be different.
To get the User position using Html5 is very easy:
function getLocation()
{
if (navigator.geolocation)
{
navigator.geolocation.getCurrentPosition(showPosition);
}
else
{
console.log("Geolocation is not supported by this browser.");
}
}
function showPosition(position)
{
console.log("Latitude: " + position.coords.latitude +
"<br>Longitude: " + position.coords.longitude);
}
Try it yourself on W3Schools Geolocation Tutorial
public static string GetLocationIPAPI(string ipaddress)
{
try
{
IPDataIPAPI ipInfo = new IPDataIPAPI();
string strResponse = new WebClient().DownloadString("http://ip-api.com/json/" + ipaddress);
if (strResponse == null || strResponse == "") return "";
ipInfo = JsonConvert.DeserializeObject<IPDataIPAPI>(strResponse);
if (ipInfo == null || ipInfo.status.ToLower().Trim() == "fail") return "";
else return ipInfo.city + "; " + ipInfo.regionName + "; " + ipInfo.country + "; " + ipInfo.countryCode;
}
catch (Exception)
{
return "";
}
}
public class IPDataIPINFO
{
public string ip { get; set; }
public string city { get; set; }
public string region { get; set; }
public string country { get; set; }
public string loc { get; set; }
public string postal { get; set; }
public int org { get; set; }
}
==========================
public static string GetLocationIPINFO(string ipaddress)
{
try
{
IPDataIPINFO ipInfo = new IPDataIPINFO();
string strResponse = new WebClient().DownloadString("http://ipinfo.io/" + ipaddress);
if (strResponse == null || strResponse == "") return "";
ipInfo = JsonConvert.DeserializeObject<IPDataIPINFO>(strResponse);
if (ipInfo == null || ipInfo.ip == null || ipInfo.ip == "") return "";
else return ipInfo.city + "; " + ipInfo.region + "; " + ipInfo.country + "; " + ipInfo.postal;
}
catch (Exception)
{
return "";
}
}
public class IPDataIPAPI
{
public string status { get; set; }
public string country { get; set; }
public string countryCode { get; set; }
public string region { get; set; }
public string regionName { get; set; }
public string city { get; set; }
public string zip { get; set; }
public string lat { get; set; }
public string lon { get; set; }
public string timezone { get; set; }
public string isp { get; set; }
public string org { get; set; }
public string #as { get; set; }
public string query { get; set; }
}
==============================
private static string GetLocationIPSTACK(string ipaddress)
{
try
{
IPDataIPSTACK ipInfo = new IPDataIPSTACK();
string strResponse = new WebClient().DownloadString("http://api.ipstack.com/" + ipaddress + "?access_key=XX384X1XX028XX1X66XXX4X04XXXX98X");
if (strResponse == null || strResponse == "") return "";
ipInfo = JsonConvert.DeserializeObject<IPDataIPSTACK>(strResponse);
if (ipInfo == null || ipInfo.ip == null || ipInfo.ip == "") return "";
else return ipInfo.city + "; " + ipInfo.region_name + "; " + ipInfo.country_name + "; " + ipInfo.zip;
}
catch (Exception)
{
return "";
}
}
public class IPDataIPSTACK
{
public string ip { get; set; }
public int city { get; set; }
public string region_code { get; set; }
public string region_name { get; set; }
public string country_code { get; set; }
public string country_name { get; set; }
public string zip { get; set; }
}

Categories