How can i save multiple collections with some common data to database? - c#

I'm trying to save collections with part common data for all and different part for each collection. I wrote hard coded way to save one collection and I don't know how I can do it for multiple collections. So this is what I have:
Controller:
[HttpPost]
public ActionResult MakeComplaint(CommonData model)
{
if (ModelState.IsValid)
{
model.CreateComplaint();
return RedirectToAction("Index");
}
}
Model:
public class CommonData
{
public string Data1 { get; set; }
public string Data2 { get; set; }
public List<DifferentData> Differents { get; set; }
SecondModel DataContainer()
{ //help needed here
SecondModel tmp = new SecondModel();
tmp.ID = Differents[0].ID; //how can I change it to save more collections?
tmp.Name = Differents[0].Name;
tmp.Data1 = Data1;
tmp.Data2 = Data2;
return tmp;
}
public int CreateComplaint()
{
var complaint = DataContainer();
db.AddComplaint(complaint);
db.Save();
}
}
public class DifferentData
{
public int ID { get; set; }
public string Name { get; set; }
}
How should my DataContainer() look in order to handle Differents[1] and more?
EDIT:
My DataContainer() is a list of objects now, so 1 problem solved
List<SecondModel> DataContainer()
{
var listOfComplaints = new List<SecondModel>;
for(int i = 0; i<Differents.Count; i++){
SecondModel tmp = new SecondModel();
tmp.ID = Differents[i].ID;
tmp.Name = Differents[i].Name;
tmp.Data1 = Data1;
tmp.Data2 = Data2;
listOfComplaints.Add(tmp)
}
return listOfComplanints;
}
EDIT2:
Working solution:
public void AddComplaint(List<SecondModel> model){
db.SecondModels.InsertAllOnSubmit(model) //saving multiple objects
}

Usually you get new Models from the page. Not as a DataContainer but as a SecondModel or another specific model. Your DataContainer and nested classes in CommonData is probably adding confusion. You can actually remove all of that, and use the code you have in AddComplaint directly from your controller like this:
[HttpPost]
public ActionResult MakeComplaint(SecondModel model)
{
if (ModelState.IsValid)
{
db.SecondModels.InsertOnSubmit(model)
return RedirectToAction("Index");
}
}
and just do something similar for another model:
[HttpPost]
public ActionResult MakeSomethingElse(ThirdModel model)
{
if (ModelState.IsValid)
{
db.ThirdModels.InsertOnSubmit(model)
return RedirectToAction("Index");
}
}

Related

How to fetch data from a class with two list inside?

I have a class with 2 list inside and don't know how to fetch through all 2 list to get all data,
thank you for reading my question.
my MODEL
namespace BaoCao.Models
{
public class ProductPage
{
public List<PRODUCT> listproduct { get; set; }
public List<TYPE_PRODUCTS> listtype_product { get; set; }
public static ProductPage getAll()
{
DB db = new DB();
ProductPage a = new ProductPage();
a.listproduct = db.PRODUCTS.ToList();
a.listtype_product = db.TYPE_PRODUCTS.ToList();
return a;
}
ProductPage()
{
}
}
}
MY VIEW
namespace BaoCao.Controllers
{
public class ProductController : Controller
{
// GET: Product
public ActionResult Product()
{
var dssp = ProductPage.getAll();
return View(dssp);
}
}
}
Product.cshtml
#model BaoCao.Models.ProductPage
#foreach (var product in Model.listproduct) {
...
}
The details are here.

Parse FHIR Patient response to json

I'm new to .Net and FHIR. I followed a few tutorial to understand how FHIR API works. I need to create an application that use only GET request to get data from server. Below, I am trying to make a request to retrieve a patient by ID in PatientRepository class. However, when I test it with Postman, it doesn't return any response. How should I change my code? Many thanks
Model:
public class Patient : Hl7.Fhir.Model.Patient
{
public string name { get; set; }
public string birthday { get; set; }
}
public class PatientList
{
public List<Patient> Patients { get; set; }
}
Controller:
public class PatientController : Controller
{
private readonly IPatientRepository _patientRepository;
public PatientController(IPatientRepository patientRepository)
{
_patientRepository = patientRepository;
}
[HttpGet]
[Route("api/GetPatientById/{id}")]
public IActionResult getPatientById(long id)
{
var model = _patientRepository.GetPatientById(id);
if (model == null)
return NotFound();
return Ok(model);
}
}
}
PatientRepository:
public class PatientRepository : IPatientRepository
{
public async Task<Patient> GetPatientById(long id)
{
var client = new FhirClient("https://fhir.****.***/hapi-fhir-jpaserver/fhir/");
client.Timeout = (60 * 100);
client.PreferredFormat = ResourceFormat.Json;
var pat = client.Read<Patient>("Patient/1");
var parser = new FhirJsonParser();
return new Patient
{
birthday = pat.birthday,
}
}
}

Modify value before I display it in the view?

I have a feeds table
Id Message Created
1 aaa 2016-02-25 12:18:51
2 bbb 2016-02-24 12:18:51
3 ccc 2015-02-25 12:18:51
I can get all the values like this
public ActionResult Index()
{
using (var db = new ApplicationDbContext())
{
var feeds = db.Feeds.ToList();
return View(feeds);
}
}
I have created a class that change date from datetime to e.g "1 day ago". And this works fine
var myTime = DateExtension.TimeAgo(DateTime.Parse("2016-02-25 12:18:51"));
I want to modify all the dates in feed with help of DateExtension.TimeAgo before I return in to the view. How can I do that?
try this:
return View(
feeds.Select(x=>
new Feed{
Id=x.Id,
Message=x.Message,
Created=DateExtension.TimeAgo(DateTime.Parse(x.Created))
}).toList());
where Feed your class, with the same fields
Use FeedDisplayModel class in your view
public class Class1TestController
{
public ActionResult Index()
{
using (var db = new ApplicationDbContext())
{
var feeds = db.Feeds.Select(itm=>new FeedDisplayModel(itm)).ToList();
return View(feeds);
}
}
}
class Feed
{
public DateTime Created { get; set; }
public int Id { get; set;}
public string Message { get; set;}
}
class FeedDisplayModel : Feed
{
public string Ago { get { return Created.TimeAgo(); } }
public FeedDisplayModel(Feed itm){
this.Created=itm.Created;
this.Id=itm.Id;
this.Message=itm.Message;
}
}
public static class DateExtension
{
public static string TimeAgo(this DateTime dt)
{
return "your implementation of ";
}
}

"Edit" action, save old data

How i can save old data in action [post]Edit?
I have these two models:
public class Task
{
public int ID { get; set; }
public int sheet_length { get; set; }
public int sheets_num { get; set; }
[Required]
public int spoolID { get; set; }
[ForeignKey("spoolID")]
public virtual Spool Spool { get; set; }
}
public class Spool
{
public int ID { get; set; }
public string name { get; set; }
public int weight { get; set; }
public int weight_meter { get; set; }
public virtual ICollection<Task> Tasks { get; set; }
}
When I create Task - Spool.Weight changes
Task.Spool.Weight = Task.Spool.Weight - (Task.sheet_length * Task.sheets_num * Task.Spool.weight_meter)
When I edit a task - I want to do this:
TaskOld.Spool.Weight = TaskOld.Spool.Weight + (TaskOld.sheet_length * TaskOld.sheets_num * TaskOld.Spool.weight_meter)
Task.Spool.Weight = Task.Spool.Weight - (Task.sheet_length * Task.sheets_num * Task.Spool.weight_meter)
But when I try to get old data in edit action
[HttpPost]
public ActionResult Edit(Task task)
{
if (ModelState.IsValid)
{
taskOld = dbContext.Tasks.Single (t => t.ID == task.ID);
////some code
db.Tasks.Attach(task);
db.SaveChanges();
return RedirectToAction("Index", "Task", new { id = task.orderID });
}
///some code }
I get an ObjectStateManager error (it has object with the same key)
The problem occurs when you attach the new task.
if (ModelState.IsValid)
{
taskOld = dbContext.Tasks.Single (t => t.ID == task.ID);
////some code
// Error here! db.Tasks already contains something for the Id
// Can't have two tasks with the same Id. Attach doesn't update the
// existing record, but adds the 'task' to the object graph for tracking.
db.Tasks.Attach(task);
db.SaveChanges();
return RedirectToAction("Index", "Task", new { id = task.orderID });
}
Both have the same Id, and the ObjectStateManager can't track two of the same object with the same Id.
A more normal approach is to map the Task input to taskOld:
if (ModelState.IsValid)
{
taskOld = dbContext.Tasks.Single (t => t.ID == task.ID);
// ... Some code ...
// taskOld is already attached to the DbContext, so just map the updated
// properties.
taskOld.Property1 = task.Property1;
taskOld.Property2 = task.Property2;
...
db.SaveChanges();
return RedirectToAction("Index", "Task", new { id = task.orderID });
}
Or, instead of assigning properties individually, you can call UpdateModel(taskOld) and it will attempt to do the same thing.
You can following Leniency code, or:
[HttpPost]
public ActionResult Edit(Task t)
{
if (ModelState.IsValid)
{
db.Entry(t).State = EntityState.Modified;
db.SaveChanges();
}
return View(t);
}

.net create object instance from abstract class

I have the following abstract class:
public abstract class TemplateBase
{
public abstract string TemplateName { get; }
public string RuntimeTypeName { get { return GetType().FullName; } }
public abstract List<AreaContainer> TemplateAreas { get; }
}
then these 2 inherited classes:
public class SingleColumnTemplate : TemplateBase
{
public override string TemplateName { get { return "Single column"; } }
public AreaContainer CenterColumn { get; private set; }
public SingleColumnTemplate()
{
this.CenterColumn = new AreaContainer("Middle");
}
private List<AreaContainer> templateAreas;
public override List<AreaContainer> TemplateAreas
{
get
{
if (this.templateAreas == null)
{
this.templateAreas = new List<AreaContainer>() { this.CenterColumn };
}
return this.templateAreas;
}
}
}
and
public class TwoColumnTemplate : TemplateBase
{
public override string TemplateName { get { return "Two column"; } }
public AreaContainer LeftColumn { get; private set; }
public AreaContainer RightColumn { get; private set; }
public TwoColumnTemplate()
{
LeftColumn = new AreaContainer("Left");
RightColumn = new AreaContainer("Right");
}
private List<AreaContainer> templateAreas;
public override List<AreaContainer> TemplateAreas
{
get
{
if (this.templateAreas == null)
{
this.templateAreas = new List<AreaContainer>() { this.LeftColumn, this.RightColumn };
}
return this.templateAreas;
}
}
}
I also have this class that is my model for editing:
public class ContentPage
{
public virtual int ContentPageId { get; set; }
public virtual string Title { get; set; }
public TemplateBase Template { get; set; }
}
Question:
for my ActionResults I have the following:
[HttpGet]
public ActionResult Edit()
{
var row = new ContentPage();
var template = new TwoColumnTemplate();
// Areas
HtmlArea html_left = new HtmlArea();
html_left.HtmlContent = "left area html content";
HtmlArea html_right = new HtmlArea();
html_right.HtmlContent = "right area html content";
template.LeftColumn.Areas.Add(html_left);
template.RightColumn.Areas.Add(html_right);
row.Template = template;
return View(row);
}
[HttpPost]
[ValidateInput(false)]
public ActionResult Edit(ContentPage row)
{
// Here i could loop through List -TemplateAreas and save each template Area to Db. I guess that would work
return this.View(row);
}
Question:
For HttpGet- how would I load row Template from the database? since it could be SingleColumnClass or TwoColumnClass.
how would my ViewModel look like to solve this?
thanks
You can write your own Model Binder that is responsible for binding TemplateBase. You will still need to have a way of knowing (in the model binder) which type you will be using a runtime, but you can always delegate that to a factory or service locator of some sort. I did a quick google search and here is a blog post I found that gives you some information for making a model binder for a similar scenario:
http://weblogs.asp.net/bhaskarghosh/archive/2009/07/08/7143564.aspx
EDIT: The blog leaves out how you tell MVC about your model binder. When the application starts, you can add your model binder to System.Web.Mvc.ModelBinders.Binders
HTH
You need to know the template type in you controller, so you can pass a parameter from the view to the controller, indicating the type (SingleColumn or TwoColumn). You could do this witn a Enum:
public enum TemplateType
{
SingleColumn,
TwoColumn
}
[HttpGet]
public ActionResult Edit(TemplateType templateType)
{
var row = new ContentPage();
TemplateBase template;
if (templateType == TemplateType.SingleColumn)
{
template = new SingleColumnTemplate();
}
else
{
template = new TwoColumnTemplate();
}
...
return View(row);
}
When you create the action link from your view you can specify:
<%= Html.ActionLink("Edit",
"Edit",
"YouController",
new
{
// singlecolumn or twocolumn
// depending on your concrete view
TemplateType = TemplateType.xxx
},
null);
I wonder if you could do something like this?
[HttpGet]
public ActionResult Edit(TemplateType templateType)
{
var row = new ContentPage();
TemplateBase template = (TemplateBase)Activator.CreateInstance(templateType);
...
return View(row);
}
templateType would have to be the exact name of your inherited classes (you can ignore case)

Categories

Resources