Looping inside razor - asp.net-mvc-4

I have field name "GroupTitle" assigned to each Control. I want to loop through each element of Control assigned to particular group.
public class Groups
{
public virtual int Id { get; set; }
public virtual string GroupTitle { get; set; }
}
public class Controls
{
public int Id { get; set; } //Id
public string Name { get; set; } //name of control/element
public string ControlType { get; set; } // checkbox, radio button, textbox, time, date
public string Caption { get; set; } //caption/title/label
public string Content { get; set; } //in case of checkbox
public bool Mandatory { get; set; } //is mandatory to select or enter its value.
public string GroupTitle { get; set; } // there will be title at the top of controls if grouped together
//public List<SelectListItem> SelectOptions { get; set; } //select/dropdown options e.g. Pakistan, Uk for country dropdown
}
Below is my code . I am not sure how to access Model variable inside nested loop. This gives me error. Also it gives me error that Where clause does not exists.
#foreach (var groups in Model.Groups)
{
foreach (var row in Model.Controls.Where("GroupTitle ==", #groups.GroupTitle;))
{
}
}

Prove this:
#foreach (var groups in Model.Groups)
{
foreach (var row in Model.Controls.ToList().Where(x => x.GroupTitle == groups.GroupTitle))
{
}
}
I think this answers probably also applies to your case.

Related

Can i add a parent record and a child record using the same _context.SaveChangesAsync()

I have the following 2 Parent/Child objects:-
public Submission()
{
SubmissionQuestionSubmission = new HashSet<SubmissionQuestionSubmission>();
}
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Npi { get; set; }
public bool Independent { get; set; }
public string Comment { get; set; }
public virtual ICollection<SubmissionQuestionSubmission> SubmissionQuestionSubmission { get; set; }
}
public partial class SubmissionQuestionSubmission
{
public int SubmissionQuestionId { get; set; }
public int SubmissionId { get; set; }
public string Answer { get; set; }
public virtual Submission Submission { get; set; }
}
and i created the following view model:-
public class SubmissionCreate
{
public Submission Submission {set; get;}
public IList<SubmissionQuestion> SubmissionQuestion { set; get; }
public IList<SubmissionQuestionSubmission> SubmissionQuestionSubmission { set; get; }
}
where i have the following action method to add a parent record (submission) and a child record (SubmissionQuestionSubmission ), but to do so, i have to issue 2 save requests to the database, one to save the parent and get its ID, while the other to save the child record and assign it the parent ID, as follow:-
public async Task<IActionResult> Create(SubmissionCreate sc)//Bind("Id,FirstName,LastName,Npi,Independent,Comment")]
{
if (ModelState.IsValid)
{
var newsubmission = _context.Submission.Add(sc.Submission);
await _context.SaveChangesAsync();
foreach (var v in sc.SubmissionQuestionSubmission)
{
v.SubmissionId = sc.Submission.Id;
_context.SubmissionQuestionSubmission.Add(v);
}
await _context.SaveChangesAsync();
TempData["message"] = "Thank You.. Your request has been submitted...";
return View("Confirmation");
}
return View(sc);
}
so my question is if i can do the above job, using one save statement instead of 2?
You don't need use two SaveChanges. You can assign newsubmission into Submission property instead of v.SubmissionId = sc.Submission.Id;.
In this case Id and ForeignKey created automatically by EF Core
var newsubmission = _context.Submission.Add(sc.Submission);
foreach (var v in sc.SubmissionQuestionSubmission)
{
v.Submission = newsubmission;
_context.SubmissionQuestionSubmission.Add(v);
}
await _context.SaveChangesAsync();
Another way
sc.Submission.SubmissionQuestionSubmission = new List<SubmissionQuestionSubmission>();
foreach (var v in sc.SubmissionQuestionSubmission)
{
sc.Submission.SubmissionQuestionSubmission.Add(v)
}
_context.Submission.Add(sc.Submission);
await _context.SaveChangesAsync();

Handling queries over related documents in RavenDB

I have a project where I have a set of forms:
public class Form
{
public string Id { get; set; }
public string Name { get; set; }
public IList<string> FieldValueIds { get; set; }
public string UserId { get; set; } // the user who completed the form.
public string FormTemplateId { get; set; }
}
Which each "implement" a form template selected at creation of the form.
public class FormTemplate
{
public string Id { get; set; }
public string Name { get; set; }
public IList<string> FieldIds { get; set; }
}
Which defines which fields are present within the form. Each field
public class FormField
{
public string Id { get; set; }
public string Name { get; set; }
public string Caption { get; set; }
public ValueType DataType { get; set; } // Enum specifying the type of data this field accepts.
}
Stores information about the field such as a description and what type it is expecting. Each FormField can be present in multiple FormTemplates with the values for the form being stored as FieldValue objects related to the Form itself.
public class FieldValue
{
public string Id { get; set; }
public string FieldId { get; set; }
public string ValueAsJsonString { get; set; }
}
Other objects include the User Object:
public class User
{
public string Id { get; set; }
public string Username { get; set; }
public string GivenNames { get; set; }
public string Surname { get; set; }
}
I would like to be able to perform a query to find all Forms completed by a user with a specified name, or all Forms where a field with name X has value Y and so forth.
I have looked into usage of indexes as specified in the documentation Indexing related documents, however the implementation as presented in the documentation threw a NotSupportedException when I implemented the example as follows:
class FormTemplates_ByFieldAndName : AbstractIndexCreationTask<FormTemplate>
{
public class Result
{
public string Name { get; set; }
public IList<string> FieldNames { get; set; }
}
public FormTemplates_ByFieldAndName()
{
Map = FormTemplates => from FormTemplate in FormTemplates
select new
{
Name = FormTemplate.Name,
FieldNames = FormTemplate.FieldIds.Select(x => LoadDocument<FormField>(x).Name)
};
}
}
// in code:
IList<FormTemplate> TestResults = session.Query<FormTemplates_ByFieldAndName.Result, FormTemplates_ByFieldAndName>()
.Where(x => x.Name == "TemplateName" || x.FieldNames.Contains("FieldName"))
.OfType<FormTemplate>()
.ToList();
As best as I can tell this was implemented correctly, however I have seen a suggestion to replace the .Contains with a .Any implementation instead. In lieu of this I have been experimenting with a different approach by applying successive .Where arguments. Like so:
var pre = session.Query<FormTemplates_ByFieldAndName.Result, FormTemplates_ByFieldAndName>();
var pr2 = pre.Where(x => x.Name == "TypeTest25");
List<FormTemplate> TestResults = pr2
.Where(x => x.FieldNames.Any(a => a == "field25"))
.OfType<FormTemplate>()
.OrderByScoreDescending()
.ToList();
Modifying the system to perform in a more factory oriented approach by applying successive filters based on a supplied string in a pre-specified format.
Is this the way I should be going for this implementation and if not what should I be changing? In particular if I am to proceed with the Indexing option how would I apply this technique to the nested relationship between Forms and FormFields through FormTemplates.
You seems to be trying to do this in a way that is mostly relational, but you don't have to.
Instead of trying to have a set of independent documents that each has part of the data, just store it all in a single document.
public class Form
{
public string Id { get; set; }
public string Name { get; set; }
public IList<FieldValue> FieldValues { get; set; }
public string UserId { get; set; } // the user who completed the form.
public string FormTemplateId { get; set; }
}
public class FieldValue
{
public string Id { get; set; }
// can store the value directly!
//public string ValueAsJsonString { get; set; }
public object Value {get; set; }
}
This will generate documents that looks like this:
{
"Id": "forms/1234",
"Name": "Tom",
"FieldValues": [
{
"Id": "FromValues/SchoolDistrictName",
"Value": "ABi195"
}
],
"UserId": "users/tom",
"FormTemplateId": "FromTemplate/1234"
}
Which is a much more natural way to model things.
At that point, you can use RavenDB's ability to index dynamic data, see the docs here:
https://ravendb.net/docs/article-page/3.5/Csharp/indexes/using-dynamic-fields

How to bind custom model class in mvc

I am new in MVC. I am working on a project where i have created a model class and also context class which is working good if i view the record in normal view.
but if i try to get the data in group by "Series_Name" and bind it into same model class it gives error. here is my code
Here is Model class and DBContextClass
[Table("tblvideo")]
public class TVSerial
{
[Key]
public Int64 Video_ID { get; set; }
public string Series_Name { get; set; }
public string Season_No { get; set; }
public string Episode_No { get; set; }
public string Episode_Name { get; set; }
public string Time_Duration { get; set; }
public string File_Url_480p { get; set; }
public string File_Url_720p { get; set; }
public string Description { get; set; }
public bool Is_Active { get; set; }
public string Image_Url_Small { get; set; }
public string Image_Url_Big { get; set; }
}
public class TvSerialContext : DbContext
{
public DbSet<TVSerial> TvSerials { get; set; }
}
Here is controller class:
public class TvSerialController : Controller
{
public ActionResult ListAllTvSerial()
{
try
{
TvSerialContext tvContext = new TvSerialContext();
List<TVSerial> tv = tvContext.TvSerials.ToList();
return View(tv);
}
catch (Exception ex)
{
return Content(ex.Message);
}
}
}
Above code works as expected, but if i am doing this :
public ActionResult ListAllSeason(string serial)
{
try
{
TvSerialContext tvContext = new TvSerialContext();
List<TVSerial> tv = tvContext.TvSerials.Where(tvs => tvs.Series_Name == serial).Distinct().ToList();
return View(tv);
}
catch (Exception ex)
{
return Content(ex.Message);
}
}
it return all rows , i just want single row from every series_name and custom field "Series_Name,Season_No,Image_Url_Big"
i don't know how to achieve this.
getting result :
Expected result:-
You could do this by creating a view model and using a .GroupBy() clause
public class TVSerialVM
{
public string SeriesName { get; set; }
public string SeasonNo { get; set; }
public string ImageUrl { get; set; }
}
and the query to project into your view model
List<TVSerialVM> model = tvContext.TvSerials.Where(t => t.Series_Name == serial)
.GroupBy(t => new { t.Series_Name, t.Season_No, t.Image_Url_Big })
.Select(t => new TVSerialVM
{
SeriesName = t.Key.Series_Name,
SeasonNo = t.Key.Season_No,
ImageUrl = t.Key.Image_Url_Big
}).ToList();
Side note: Your duplicating data in the database (the season number and the image url). You should consider moving the image urls to another table with a relationship to the season number.
The reason you are getting multiple values even though you are using distinct is the Distinct method does not know what "equal" is for TVSerial.
You can use Distinct with IEqualityComparer.
https://msdn.microsoft.com/en-us/library/vstudio/bb338049(v=vs.100).aspx
Distinct is not guaranteed to on custom objects it doesn't know what to compare. I have used this SO in the past to make my custom object work with Distinct.
Creating a distinct list of custom type in C#

#Html.LisboxFor Model Binding for multiple items

My Class is
public partial class Team
{
public int TeamId { get; set; }
public string TeamName { get; set; }
public string TeamDescription { get; set; }
public virtual IList<Trials> Trials { get; set; }
}
Trials is anothetr calss
public partial class Trials
{
public int TrialID { get; set; }
public string Name { get; set; }
public int TrialTyp_RefID { get; set; }
public bool isChk { get; set; }
public virtual ICollection<Team> Team { get; set; }
}
in my view I amn trying to bind the ListBoxFor with Trials inseide the team
#model Trials.Classes.Team
<td colspan="2">
#Html.ListBoxFor(model=> model.Trials,
new SelectList(ViewBag.trials,"TrialID", "Name"),
new { #class = "chosen-select", data_placeholder = "Select Trials...", style = "width:500px;", tabindex = "4" }
)
</td>
I cant get any value for Trials calss in the controller ..It shows null but I select multi values from listbox
A multiple select only posts back an array of primitive values. It does not post back a collection of complex objects.
You need a view model with a property to bind the selected Trials
public class TeamVM
{
public int TeamId { get; set; }
....
public int[] SelectedTrials { get; set; }
public SelectList Trials { get; set; } // Assign this in your controller rather than using ViewBag
}
then in you view
#Html.ListBoxFor(m => m.SelectedTrials, Model.Trials)
When you post back, Team.SelectedTrials will contain and array of the selected TrialID values.
I changed the Team class as
public partial class Team
{
public int TeamId { get; set; }
public string TeamName { get; set; }
public string TeamDescription { get; set; }
public virtual IList<Trials> Trials { get; set;
public int[] AuthorisedTrials { get; set; }
}
and in View
#model Trials.Classes.Team
<td colspan="2">
#Html.ListBoxFor(model=> model.AuthorisedTrials ,
new SelectList(ViewBag.trials,"TrialID", "Name"),
new { #class = "chosen-select", data_placeholder = "Select Trials...", style = "width:500px;", tabindex = "4" }
)
</td>
and in my controller I was able to get the Vlaues for Selected Trials

EF5 Entry not updating

Im trying to update an entry with EF5 with the following actionresult:
[HttpPost]
public ActionResult Edit(int id, IEnumerable<HttpPostedFileBase> files)
{
if (ModelState.IsValid)
{
Reference reference = db.References.Single(x => x.Id == id);
db.Entry(reference).State = EntityState.Modified;
db.SaveChanges();
//Other stuff regarding files/images
return RedirectToAction("Index");
}
return View();
}
Nothing happens. When I debug it, it goes trough the code as everything was fine. But nothing is updated in the db.
Here's the model if needed:
public class Reference
{
public int Id { get; set; }
public string Headline { get; set; }
public string Text { get; set; }
public DateTime Date { get; set; }
public IEnumerable<HttpPostedFileBase> ImageUploadMain { get; set; }
public String MainFileName { get; set; }
public IEnumerable<HttpPostedFileBase> ImageUpload { get; set; }
public virtual ICollection<Image> Files { get; set; }
public virtual ICollection<RefProperties> Properties { get; set; }
public int CategoryId { get; set; }
public virtual Category Category { get; set; }
}
public class Image
{
public int Id { get; set; }
public string FileName { get; set; }
public virtual Reference Reference { get; set; }
}
public class RefProperties
{
public int Id { get; set; }
public string Key { get; set; }
public string Value { get; set; }
}
public class Category
{
public int CategoryId { get; set; }
public string Name { get; set; }
public virtual ICollection<Reference> References { get; set; }
}
Not only is the related entries not updated, a main property like "Headline" cant be updated either. What am I doing wrong? Create/delete works fine btw.
As Gert Arnold says, you're not actually modifying any of the Reference values so nothing will be updated. By calling db.Entry(reference).State = EntityState.Modified you're just setting the retrieved entity's state to modified in the ChangeTracker. When you call SaveChanges() it's just going to update the Reference record in the database with the same values that you fetched.
You need to update some of the Reference instance properties to see a change.
[HttpPost]
public ActionResult Edit(int id, IEnumerable<HttpPostedFileBase> files)
{
if (ModelState.IsValid)
{
Reference reference = db.References.Single(x => x.Id == id);
reference.HeaderText = "Changed";
/* No need to interact with the change tracker as the entity is already tracked and you've made a change */
// db.Entry(reference).State = EntityState.Modified;
/* Create/Modify/Update/Delete other entities */
db.SaveChanges();
//Other stuff regarding files/images
return RedirectToAction("Index");
}
return View();
}
Heres what I was looking for:
TryUpdateModel(reference, "");
It has a shitload of overloads. This works though