How to access data controller / data model from ApiController? - asp.net

I have a ScoreDataModelsController that contains the following Action Method:
public ActionResult Getnames()
{
return View(db.ScoreDataModels.ToList());
}
In Views I have the corresponding ScoreDataModels folder containing Getnames.cshtml:
#model IEnumerable<WebApplication1.Models.ScoreDataModel>
#{
ViewBag.Title = "Get Names";
Layout = "~/Views/Shared/_emptyLayout.cshtml";
}
<table class="table">
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.Name)
</td>
</tr>
}
</table>
This all works fine. Now I would like to make this data (i.e. Names) accessible as json/XML using REST. I have managed to get the ApiController working with the standard settings and by opening http://.../api/Andi i get the values from the string[] in XML format:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
namespace WebApplication1.Controllers
{
public class AndiController : ApiController
{
// GET api/<controller>
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2", "und en dritte" };
//Here I need help: ScoreDataModelsController sdm = new ScoreDataModelsController();
// var res = from r in sdm
}
// GET api/<controller>/5
public string Get(int id)
{
return "value";
}
// POST api/<controller>
public void Post([FromBody]string value)
{
}
// PUT api/<controller>/5
public void Put(int id, [FromBody]string value)
{
}
// DELETE api/<controller>/5
public void Delete(int id)
{
}
}
}
Now, instead of "value1, value2 ..." I would like to get the names from my ScoreDataModel / ScoreDataModelsController.
The ScoreDataModel looks like this. I have used this model to create the controller and view by scaffolding in Visual Studio:
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Web;
namespace WebApplication1.Models
{
public class ScoreDataModel
{
[Key]
public int ID { get; set; }
public string Name { get; set; }
public int Score { get; set; }
}
}
I would very much appreciate if you could lead me into the right direction to get this REST API working with my existing data controller / data model.

Create a central class which holds your data access logic, something like this:
public class DataRepository
{
private DatabaseContext db = new DatabaseContext();
public List<ScoreDataModel> GetNames()
{
return db.ScoreDataModels.ToList();
}
}
Now you can use this class to access your data from both the MVC controller and the api controller:
public class AndiController : ApiController
{
private DataRepository dbRepo = new DataRepository();
public IEnumerable<ScoreDataModel> Get()
{
List<ScoreDataModel> names = dbRepo.GetNames();
return names;
}
}

use this
var data= db.ScoreDataModels.ToList()
List<String>list=new List<String>();
foreach(var r in data)
{
list.add(r.Name);
}
return list;

Related

Why ModelState is getting false as validation?

My ModelState is getting false everytime i run the code .This is simply a file upload mvc .net core code. Migration is also perfectly executed. However whenever i try to submit the form after uploading an image the form gets reset. Due to which it failed to get store in the database.
Model code (Image.cs)
using Microsoft.AspNetCore.Http;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Threading.Tasks;
namespace FileUpload.Models
{
public class Image
{
[Key]
public int Iid { get; set; }
[Required]
public string Iname { get; set; }
[Required]
[NotMapped]
public IFormFile Iimg { get; set; }
}
}
Controller Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.EntityFrameworkCore;
using FileUpload.Data;
using FileUpload.Models;
using Microsoft.AspNetCore.Hosting;
using System.IO;
namespace FileUpload.Controllers
{
public class ImagesController : Controller
{
private readonly AppDbContext _context;
private readonly IWebHostEnvironment _hostEnvironment;
public ImagesController(AppDbContext context, IWebHostEnvironment hostEnvironment)
{
_context = context;
_hostEnvironment = hostEnvironment;
}
// GET: Images
public async Task<IActionResult> Index()
{
return View(await _context.Images.ToListAsync());
}
// GET: Images/Details/5
public async Task<IActionResult> Details(int? id)
{
if (id == null)
{
return NotFound();
}
var image = await _context.Images
.FirstOrDefaultAsync(m => m.Iid == id);
if (image == null)
{
return NotFound();
}
return View(image);
}
// GET: Images/Create
public IActionResult Create()
{
return View();
}
// POST: Images/Create
// To protect from overposting attacks, enable the specific properties you want to bind to.
// For more details, see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create(Image image)
{
if (ModelState.IsValid)
{
if(image.Iimg != null)
{
string wwwRootPath = _hostEnvironment.WebRootPath;
string fileName = Path.GetFileNameWithoutExtension(image.Iimg.FileName);
string ext = Path.GetExtension(image.Iimg.FileName);
image.Iname = fileName + DateTime.Now.ToString("yymmssfff") + ext;
string path = Path.Combine(wwwRootPath + "/Image/" + fileName);
using (var fileStream = new FileStream(path, FileMode.Create))
{
await image.Iimg.CopyToAsync(fileStream);
}
}
_context.Add(image);
await _context.SaveChangesAsync();
return RedirectToAction("Index");
}
return View(image);
}
}

Passing Multiple Dataset to View [MVC]

I am new to MVC, I referred this link (https://www.aspsnippets.com/Articles/Pass-Send-DataSet-DataTable-from-Controller-to-View-in-ASPNet-MVC.aspx) and passing data from Controller, but my project contains multiples Tables and I need to pass the data from Model->Controller->View.
I am facing error while doing this. Kindly check and provide the solution for my issue.
Error While running the Application
Server Error in '/' Application.
The model item passed into the dictionary is of type 'MyClassModel.Models.MyClass', but this dictionary requires a model item of type 'System.Collections.Generic.IEnumerable`1[MyClassModel.Models.MyClass]'.
<--Model--> (Data Representation)
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace MyClassModel.Models
{
public class Myclass
{
public List<int> Colors_ID { get; set; }
public List<string> ColorsInfo { get; set; }
public List<int> Completexity_code { get; set; }
public List<string> Completexity_name { get; set; }
public List<int> DeptCompletexity_code { get; set; }
public List<string> DeptCompletexity_name { get; set; }
}
}
<--Model--> (Business Logics)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;
namespace MyClassModel.Models
{
public class MyClassBL
{
string conn = ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString;
public DataSet details()
{
DataSet ds = new DataSet();
using (SqlConnection con = new SqlConnection(conn))
{
SqlCommand cmd = new SqlCommand("ItrackDropdown", con);
con.Open();
SqlDataAdapter da = new SqlDataAdapter(cmd);
da.Fill(ds);
}
return ds;
}
}
}
<--Controller-->
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using MyClassModel.Models;
using System.Data;
namespace MyClassModel.Controllers
{
public class Home : Controller
{
//
// GET: /Home/
public ActionResult Index()
{
MyClass newobj=new MyClass();
MyClassBL obj = new MyClassBL();
newobj.Colors_ID= obj.details().Tables[0].AsEnumerable().Select(x => x.Field<int>("Colors_ID")).ToList();
newobj.ColorsInfo = obj.details().Tables[0].AsEnumerable().Select(x => x.Field<string>("ColorsInfo")).ToList();
newobj.Completexity_code = obj.details().Tables[1].AsEnumerable().Select(x => x.Field<int>("Complexity_code")).ToList();
newobj.Completexity_name = obj.details().Tables[1].AsEnumerable().Select(x => x.Field<string>("Complexity_name")).ToList();
newobj.DeptCompletexity_code = obj.details().Tables[2].AsEnumerable().Select(x => x.Field<int>("Complexity_code")).ToList();
newobj.DeptCompletexity_name = obj.details().Tables[2].AsEnumerable().Select(x => x.Field<string>("Complexity_name")).ToList();
return View(newobj);
}
}
}
<--View-->
#model IEnumerable<MyClass.Models.MyClass>
#{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<title>Index</title>
</head>
<body>
<p>
#Html.ActionLink("Create New", "Create")
</p>
<table>
#foreach (var item1 in #Model.Select(x => x.Colors_ID))
{
<tr>
<td>
#item1
</td>
</tr>
}
#foreach (var item in Model)
{
<tr>
<td>
#Html.ActionLink("Edit", "Edit", new { /* id=item.PrimaryKey */ }) |
#Html.ActionLink("Details", "Details", new { /* id=item.PrimaryKey */ }) |
#Html.ActionLink("Delete", "Delete", new { /* id=item.PrimaryKey */ })
</td>
</tr>
}
</table>
</body>
</html>
Two suggestions for your references:
1) Model
a) Model name,
According to the controller, the Model name of the first one need update that the following line:
public class ItrackDD
should be
public class MyClass
b) Model Design should match the database. it will impact how to fix the error according to #2.
All of the members of the model ItrackDD are list, are you sure?
2) The error message should come from:
In the controller, it returned the newobj of type Myclass as in the following code line, which would be passed to the view
return View(newobj);
but in the view, it expect a dictionary as in this line:
#model IEnumerable<MyClass.Models.MyClass>

Calling any method produces the results of the Get() instead of their methods

This is probably a badly worded question and this is my first web api so I could be doing something completely wrong. I have my Controller and my Model, in my Controller I have 3 methods, string[] Apples string[]Get Judgment GetJudgmentByStateCaseId. I'm trying to call of of them using the following urls but all of the results come from Get() data.
/api/judgment
/api/apples
/api/GetJudgmentByStateCaseId
`JudgmentController.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using WebApplicationsWData.Models;
namespace WebApplicationsWData.Controllers
{
public class JudgmentController : ApiController
{
public string[] Apples()
{
return new string[]
{
"as","B"
};
}
public string[] Get()
{
return new string[]
{
"as","C"
};
}
public Judgment GetJudgmentByStateCaseId(string State, string CaseId)
{
Judgment judgement = new Judgment
{
CaseId = "1",
State = "MeVMe"
};
if (judgement == null)
throw new HttpResponseException(HttpStatusCode.NotFound);
return judgement;
}
}
`Judgment.cs
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
namespace WebApplicationsWData.Models
{
public class Judgment
{
[Required]
public string State { get; set; }
[Required]
public string CaseId { get; set; }
}
}
And here is my RouteConfig
namespace WebApplicationsWData
{
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
}
}
Okay so this question should be worded How to support multiple methods for asp api. I wanted multiple get methods, so essential this post here was the answer `
https://www.codeproject.com/Tips/832045/Implementing-a-Basic-REST-Based-ASP-NET-Web-API-Se
And yep it works now :)

Displaying SQL Query Results in View

I'm new to MVC 5 with .net
Basically I'm just trying to get my bearings and I want to display some generic queries (disregard the fact that im using the master db, I just want to get the functions working right now). I'm using the authentication 2.0 which has an applicatindbcontext, but I created my own context but since I'm not really wanting to create a model (which could be the problem) I didn't know what to create for properties:
public class MasterModel : DbContext
{
public MasterModel() : base("MasterDatabaseConnection")
{ }
}
I created the controller like:
public class MasterController : Controller
{
private MasterModel db = new MasterModel();
// GET: Statistics
public ActionResult Index()
{
return View();
}
public ActionResult GetVersion()
{
string query = "SELECT ##VERSION AS Version";
IEnumerable<MasterModel> data = db.Database.SqlQuery<MasterModel>(query);
return View(data.ToList());
}
}
And finally I'm trying to figure out how to display the results in the view...and I'm completely lost (although it's possible I was lost in one of the previous steps).
#model IEnumerable<IdentitySample.Models.MasterModel>
#{
ViewBag.Title = "Index";
}
#WTF.Am.I.SupposedToPutHere
I've followed some tutorials where I've created CRUD style model view controllers, but I guess I'm not drawing the connection on how to just submit informational queries and display the results.
Create a Context:
public class MasterModel : DbContext
{
public MasterModel() : base("MasterDatabaseConnection")
{ }
public DbSet<MyModel> ModelOBJ { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<ModelOBJ>().ToTable("tblModelOBJ");
}
}
Create a Model:
Public cLass MyModel
{
public int ID {get;set;}
public string Name {get;set;}
}
Public cLass MyModelRepository
{
public List<MyModel> GetALlModelFromDB()
{
MasterModel md = new MasterModel();
return md.ModelTosend.toList();
}
}
In your Controller:
public ActionResult Index()
{
return View(new MyModelRepository().GetALlModelFromDB());
}
In your View:
#model IEnumerable<IdentitySample.Models.MyModel>
#{
ViewBag.Title = "Index";
}
#foreach(var item in Model)
{
#:<div>#item.ID #item.Name </div>
}

Web Api with OData v4 throwing exception on $select

I'm using the latest version of WebApi and OData and everything is set up to work right. The only problem is when I try to use $select .
It throws the error bellow
Object of type 'System.Linq.EnumerableQuery`1[System.Web.OData.Query.Expressions.SelectExpandBinder+SelectAll`1[WebApplication1.Controllers.Person]]' cannot be converted to type 'System.Collections.Generic.IEnumerable`1[WebApplication1.Controllers.Person]'.
I looked at the documentation and their suggestion is to use [Queryable] on top of the Get method in the controller or the in WebApiConfig to use config.EnableQuerySupport and neither of these are available options. I'm currently using [EnableQuery]
EDIT
OdataController:
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using System.Web.OData;
using System.Xml.Serialization;
namespace WebApplication1.Controllers
{
public class PeopleController : ODataController
{
// GET api/values
[EnableQuery]
public IQueryable<Person> Get()
{
return new Person[] { new Person()
{
Id = 1,
FirstName = "Testing",
LastName = "2"
}, new Person()
{
Id = 2,
FirstName = "TestTest",
LastName = "3"
} }.AsQueryable();
}
// GET api/values/5
public Person Get(int id)
{
return new Person()
{
Id = 3,
FirstName = "Test",
LastName = "1"
};
}
// POST api/values
public void Post([FromBody]Person value)
{
}
// PUT api/values/5
public void Put(int id, [FromBody]Person value)
{
}
// DELETE api/values/5
public void Delete(int id)
{
}
}
public class Person
{
[Key]
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
}
WebApiConfig
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Http;
using System.Web.OData;
using System.Web.OData.Builder;
using System.Web.OData.Extensions;
using System.Web.OData.Formatter;
using WebApplication1.Controllers;
namespace WebApplication1
{
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
// Web API routes
config.MapHttpAttributeRoutes();
var odataFormatters = ODataMediaTypeFormatters.Create();
config.Formatters.InsertRange(0, odataFormatters);
ODataModelBuilder builder = new ODataConventionModelBuilder();
builder.EntitySet<Person>("People");
config.AddODataQueryFilter();
config.MapODataServiceRoute(
routeName: "ODataRoute",
routePrefix: "api",
model: builder.GetEdmModel());
}
}
}
UPDATE 2
seems to only throw an error retrieving the data in xml format. Json seems to work
This is a known limitation of the XmlMediaTypeFormatter class from the System.Net.Formatting Nuget package. The implementation of the JSON formatter does support the $select and $expand commands but these are not available when content negotiation determines that XML should be returned.
You should look into implementing OData endpoints (as opposed to WebAPI endpoints) should you need to return XML formatted responses. More information on how this can be done can be found here:
http://www.asp.net/web-api/overview/odata-support-in-aspnet-web-api/supporting-odata-query-options
Found a solution. It isn't perfect but it does work!
Maybe it will be useful for someone because I've spent on it few hours of research and trying.
Step #1 create custom xml formatter:
public class CustomXmlFormatter : MediaTypeFormatter
{
private JsonMediaTypeFormatter jFormatter = null;
public CustomXmlFormatter(JsonMediaTypeFormatter jFormatter)
{
SupportedMediaTypes.Add(new System.Net.Http.Headers.MediaTypeHeaderValue("application/xml"));
this.jFormatter = jFormatter;
}
public override bool CanReadType(Type type)
{
return false;
}
public override bool CanWriteType(Type type)
{
return true;
}
public override Task WriteToStreamAsync(Type type, object value, System.IO.Stream writeStream, System.Net.Http.HttpContent content, System.Net.TransportContext transportContext)
{
return Task.Factory.StartNew(() =>
{
using (MemoryStream ms = new MemoryStream())
{
var tsk = jFormatter.WriteToStreamAsync(type, value, ms, content, transportContext);
tsk.Wait();
ms.Flush();
ms.Seek(0, SeekOrigin.Begin);
var xDoc = XDocument.Load(JsonReaderWriterFactory.CreateJsonReader(ms, new XmlDictionaryReaderQuotas()));
using (XmlWriter xw = XmlWriter.Create(writeStream))
{
xDoc.WriteTo(xw);
}
}
});
}
}
Step #2 register it in startup section:
var formatters = ODataMediaTypeFormatters.Create();
var jsonFormatter = config.Formatters.JsonFormatter;
var customXmlFormatter = new CustomXmlFormatter(jsonFormatter);
customXmlFormatter.AddQueryStringMapping("$format", "cxml", "application/xml");
config.Formatters.Add(customXmlFormatter);
use it as
http://url..../actionName?$format=cxml&$select=ObjectName,ObjectId

Resources