Loop through datatable to create json in web api - api

I am trying to create a JSON response from the WebServices that return a dataset. How can I loop through the datatable and put those values in client model? When I try to loop through the datatable I get invalid initiater error.
Here is my code:
public class ClientsController : ApiController
{
public IEnumerable<ClientResponseModels> GetAllClients()
{
//retrieves list of all the clients
var dsClients = ClientRepository.GetAllClients();
//create a json response object
ClientResponseModels[] response = new ClientResponseModels[]
{
new ClientResponseModels
{
UserId= userDetails.UserID,
UserName=userDetails.LoginName,
LocationName=centreLocation.ToString(),
Clients = new List<ClientModels>
{
foreach(DataRow row in dsClients.Tables[0].rows)
{
new ClientModels //these values need to come from datatable
{
Id =Convert.ToInt32(row["client_id"]),
ClientName=Convert.ToString(row["client_nme"])",
DOB= Convert.ToDateTime(row["birth_date]")
}
}
}
}
};
return response;
}
else {
throw new HttpResponseException(HttpStatusCode.Forbidden);
}
}

I you use entity framework change datacontext configuration.
MyDataContext db = new MyDataContext();
db.Configuration.LazyLoadingEnabled = false;
db.Configuration.ProxyCreationEnabled = false;

I think the function is the cause as your code I'd looping through a queryable. You can retrieve the data first before looping e.g. GetAllClients().ToList()

Related

How to pass list values from an Action method to another in the same controller?

How to pass data from a method to another inside a controller and display.
The first method have list of values and this has to pass to the another and display that data from the view
first action method:
[HttpPost]
public ActionResult matchpin(string id)
{
int d = Convert.ToInt32(id);
List<pin> plist = new List<pin>();
using (SqlConnection con = new SqlConnection(constring))
{
using (SqlCommand cmd = new SqlCommand("getpin", con))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#pin", d);
con.Open();
SqlDataReader reader = cmd.ExecuteReader();
while (reader.Read())
{
var pin = new pin()
{
// Vid=Convert.ToInt32(reader["Vid"]),
po = Convert.ToString(reader["po"]),
};
plist.Add(pin);
}
}
}
return RedirectToAction("Index","home",new{ s =plist});
}
second action method:
public ActionResult Index(List<pin> plist)
{
// return View();
ViewBag.s = plist;
return View("Index");
//return new ContentResult { Content =TempData["Data"].ToString() };
}
redirect in the first action method has to be
return RedirectToAction("Index","home",new{plist});
instead of
return RedirectToAction("Index","home",new{s=plist});
because ASP MVC framework match it by method parameter name so you have to pass it with the same name in the action method two which is plist.
Using action you can pass limited data.
Mvc provides tempdata to pass data from one action to another.
You can also using session for storing data.
e. g
For passing data:
TempData["mydata"] =myList;
For data retrieval :
var data=TempData["mydata"] ;
Hope that clarify you question.
Using action you can pass limited data.
Mvc provides TempData to pass data from one action to another.
You can also using session for storing data.
e.g
For storing data:
TempData["mydata"]=data;
For retrieving :
var storedData=TempData["mydata"]
You can use TempData: first store your value in TempData, and then redirectToAction:
TempData.MyList=plist;
return RedirectToAction("Index","home");

Pass Generic Object Dynamically

I am trying to dynamically show a table depending on what tableName user has selected from dropdown. I am passing a json object from my web Controller(.Net Core) so in order to do it, I am first converting my dataTable to list of objects using function
public static List<T> ConvertTableToList<T>(this DataTable table) where T : class, new()
{
try
{
List<T> list = new List<T>();
foreach (var row in table.AsEnumerable())
{
T obj = new T();
foreach (var prop in obj.GetType().GetProperties())
{
try
{
PropertyInfo propertyInfo = obj.GetType().GetProperty(prop.Name);
propertyInfo.SetValue(obj, Convert.ChangeType(row[prop.Name], propertyInfo.PropertyType), null);
}
catch(Exception ex)
{
throw ex;
}
}
list.Add(obj);
}
return list;
}
catch
{
return null;
}
}
and call this function in my Get Request
public IActionResult GetTableDetailsByTableName(string TableNameSelected)
{
//To get the data for the Table Selected
DataTable TableDetails = ReferenceTableLogics.getTableDetails(TableNameSelected);
var TableDetailsInList = ConverterClass.ConvertTableToList<CSBM_AGE_BAND>(TableDetails);
return Ok(TableDetailsInList);
}
Now the issue is that I need to tell my class Name (eg CSBM_AGE_BAND in this case) depending on what user has selected in dropdown (TableNameSelected).
Is there any way by which I can dynamically pass this class name to my function ConvertTableToList ?
Using reflection you can invoke your generic extension method:
Type genericType = Type.GetType("YourNamespace.ConverterClass");
MethodInfo methodInfo = typeof(ConverterClass).GetMethod("ConvertTableToList", BindingFlags.Public | BindingFlags.Static).MakeGenericMethod(genericType);
var TableDetailsInList = methodInfo.Invoke(null, new object[]{ TableDetails });

Rendering #Html.Action("actionName","controllerName") at runtime , fetching from database in MVC4

My requirement is to fetch html data from database and render it on view. But if that string contains #Html.Action("actionName","controllerName"), i need to call perticular controller action method also.
I am rendering my html on view using #Html.Raw().
Eg: Below is the html string stored in my database
'<h2> Welcome To Page </h2> <br/> #Html.Action("actionName", "controllerName")'
So when it render the string, it execute mentioned controller and action too.
Any help will be appreciated.
You can try RazorEngine to allow string template in razor executed.
For example, sample code from the project site http://antaris.github.io/RazorEngine/:
using RazorEngine;
using RazorEngine.Templating; // For extension methods.
string template = "Hello #Model.Name, welcome to RazorEngine!";
var result =
Engine.Razor.RunCompile(template, "templateKey", null, new { Name = "World" });
But there is one catch, Html and Url helpers are defined in the Mvc framework, hence it is not supported by default.
I will suggest you try to create your template by passing model so that you don't have to use #Html.Action.
If you can not avoid it, then there is possible a solution suggested by another so answer https://stackoverflow.com/a/19434112/2564920:
[RequireNamespaces("System.Web.Mvc.Html")]
public class HtmlTemplateBase<T>:TemplateBase<T>, IViewDataContainer
{
private HtmlHelper<T> helper = null;
private ViewDataDictionary viewdata = null;
public HtmlHelper<T> Html
{
get
{
if (helper == null)
{
var writer = this.CurrentWriter; //TemplateBase.CurrentWriter
var context = new ViewContext() { RequestContext = HttpContext.Current.Request.RequestContext, Writer = writer, ViewData = this.ViewData };
helper = new HtmlHelper<T>(vcontext, this);
}
return helper;
}
}
public ViewDataDictionary ViewData
{
get
{
if (viewdata == null)
{
viewdata = new ViewDataDictionary();
viewdata.TemplateInfo = new TemplateInfo() { HtmlFieldPrefix = string.Empty };
if (this.Model != null)
{
viewdata.Model = Model;
}
}
return viewdata;
}
set
{
viewdata = value;
}
}
public override void WriteTo(TextWriter writer, object value)
{
if (writer == null)
throw new ArgumentNullException("writer");
if (value == null) return;
//try to cast to RazorEngine IEncodedString
var encodedString = value as IEncodedString;
if (encodedString != null)
{
writer.Write(encodedString);
}
else
{
//try to cast to IHtmlString (Could be returned by Mvc Html helper methods)
var htmlString = value as IHtmlString;
if (htmlString != null) writer.Write(htmlString.ToHtmlString());
else
{
//default implementation is to convert to RazorEngine encoded string
encodedString = TemplateService.EncodedStringFactory.CreateEncodedString(value);
writer.Write(encodedString);
}
}
}
}
Then you have to use HtmlTemplateBase (modified base on https://antaris.github.io/RazorEngine/TemplateBasics.html#Extending-the-template-Syntax):
var config = new TemplateServiceConfiguration();
// You can use the #inherits directive instead (this is the fallback if no #inherits is found).
config.BaseTemplateType = typeof(HtmlTemplateBase<>);
using (var service = RazorEngineService.Create(config))
{
string template = "<h2> Welcome To Page </h2> <br/> #Html.Action(\"actionName\", \"controllerName\")";
string result = service.RunCompile(template, "htmlRawTemplate", null, null);
}
in essence, it is telling the RazorEngine to use a base template where mvc is involved, so that Html and Url helper can be used.

NHibernate Dynamic Component Default Value Issue

All of my entities (that are mapped to a database table) inherit from an entity class with a dynamic component on it called Attributes e.g.:
public abstract class Entity<T> {
public virtual T Id { get; set; }
private IDictionary _attributes;
public virtual IDictionary Attributes {
get { return _attributes ?? (_attributes = new Hashtable()); }
set { _attributes = value; }
}
}
The Attributes collection allows me to add extra fields to each entity without directly changing the entity itself. This allows me to make my application more modular.
For example say I have the following entity:
public class User : Entity<int> {
public virtual string Name { get; set; }
}
Now say I have a Forum module which needs a NumPosts property against the User. I would add the field against the Users table in the database. This field is non nullable and has a default value of 0. I then map the field using the dynamic component against the User entity.
However when I try inserting the user by saying:
session.Save(new User() { Name = "Test" });
It throws an error as it's expecting me to set a value for NumPosts and the generated SQL would be something like:
INSERT INTO Users (Name, NumPosts) VALUES ('Test', NULL)
However NumPosts does not allow nulls and hence the error. Ideally I'd like it to say the following if the Attributes collection does not contain an entry for NumPosts:
INSERT INTO Users (Name) VALUES ('Test')
An alternative is to say the following which would work fine:
session.Save(new User() { Name = "Test", Attributes = new Hashtable() { { "NumPosts", 0 } } });
The problem I have is that I don't want the modules to have a dependency on each other and I can't really say this.
For reference here's a bare bones version of session factory method which maps the NumPosts field:
return Fluently.Configure()
...
.ExposeConfiguration(c => {
// Get the persistent class
var persistentClass = c.GetClassMapping("User");
// Create the attributes component
var component = new Component(persistentClass);
// Create a simple value
var simpleValue = new SimpleValue(persistentClass.Table);
// Set the type name
simpleValue.TypeName = "Int32";
// Create a new db column specification
var column = new Column("NumPosts");
column.Value = simpleValue;
column.Length = 10;
column.IsNullable = false;
column.DefaultValue = "0";
// Add the column to the value
simpleValue.AddColumn(column);
// Ad the value to the component
component.AddProperty(new Property() { Name = column.Name, Value = simpleValue });
// Add the component property
persistentClass.AddProperty(new Property() { Name = "Attributes", Value = component });
})
.BuildConfiguration();
I'd appreciate if someone could let me know if this is possible. Thanks
You know how to make it working as described above:
... An alternative is to say the following which would work fine:
session.Save(new User()
{
Name = "Test", Attributes = new Hashtable() { { "NumPosts", 0 } }
});
... The problem I have is that I don't want the modules to have a dependency on each other and I can't really say this...
In case, that the biggest issue is the explicit Attributes initialization ("...I don't want the modules to have a dependency...") we can use:
12.2. Event system
So, with Listener like this:
[Serializable]
public class MyPersistListener : NHibernate.Event.ISaveOrUpdateEventListener
{
public void OnSaveOrUpdate(SaveOrUpdateEvent #event)
{
var entity = #event.Entity as Entity<int>; // some interface IHaveAttributes
if (entity == null) // would be more appropriate
{
return;
}
var numPosts = entity.Attributes["NumPosts"] as int?;
if (numPosts.HasValue)
{
return;
}
entity.Attributes["NumPosts"] = 0;
}
}
Based on this doc snippet:
Configuration cfg = new Configuration();
ILoadEventListener[] stack = new ILoadEventListener[] { new MyLoadListener(), new DefaultLoadEventListener() };
cfg.EventListeners.LoadEventListeners = stack;
This should be the init in our case:
.ExposeConfiguration(c => {
var stack = new ISaveOrUpdateEventListener [] { new MyPersistListener() };
c.EventListeners.SaveEventListeners= stack;

How to request same parameter twice in query string?

I am trying to request the following query string url: api/item?name=storm&name=prest
I am using the following code below and I cannot get the code to work.
public class ItemController : ApiController
{
private cdwEntities db = new cdwEntities();
public HttpResponseMessage Get([FromUri] Query query)
{
var data = db.database_ICs.AsQueryable();
if (query.name != null)
{
**data = data.Where(c => c.Name.Split("&").Contains(query.name));**
}
if (query.id!= null)
{
data = data.Where(c => c.ID== query.id);
}
if (!data.Any())
{
var message = string.Format("No data was found");
return Request.CreateErrorResponse(HttpStatusCode.NotFound, message);
}
return Request.CreateResponse(HttpStatusCode.OK, data);
}
}
Any help would be very much appreciated.
You can use post Api and send array of [name].
name = [item1,item2....]
public void Post([FromBody] List<string> name) {
}
You can not pass same name key in Querystring. Browser/Code did not identified which is correct value, if you want multiple value then pass as a object.