Not sure how to word this...
I have a Model, here is a section of it:
public class AnswerSheet
{
public string Q1 { get; set; }
public string Q2 { get; set; }
public string Q3 { get; set; }
public string Q4 { get; set; }
I am using a Viewmodel to reuse the same view to answer each question separately. It is almost working. Is there any way I can use my controller as follows to dynamically assign the model.q#, ex:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult CreateNextQ([Bind(Include = "ID, qCounter, Question,Comment")] AnswerSheetCreateVM answerVM)
{
if (ModelState.IsValid)
{
string questionAns = answerVM.Question + answerVM.Comment;
AnswerSheet answer= db.AnswerSheets.Find(answerVM.ID);
//THIS PART HERE IS WHERE I HAVE A PROBLEM
answer.Q(answerVM.qCounter) = questionAns;
//That one line above
db.AnswerSheets.Add(answer);
db.SaveChanges();
So basically can I get data from my controller variable (qCounter in this case) and assign it to my model like Model.Q(qcounter)
As a side note I am open to suggestion on how to word this question or what tags to assign to it.
I found this post useful:
Set object property using reflection
This is what I ended up doing, still have to test performance:
string test = string.Format("Q" + answerVM.qCounter);
string questionAns = (answerVM.Question + " - " + answerVM.NoComment);
AnswerSheet answer= db.AnswerSheets.Find(answerVM.ID);
if (answer== null)
{
return HttpNotFound();
}
answer.GetType().GetProperty(test).SetValue(answer, questionAns, null);
db.Entry(answer).State = EntityState.Modified;
db.SaveChanges();
Maybe that will help someone down the line....NOt sure if this counts as using reflection....
Related
Step 1: I have created a C# application called : Student details
Step 2: Added four TextBoxes and named them as :
Image below to refer:
Studentname.Text
StudentSurname.Text
StudentCity.Text
StudentState.Text
DATA INSIDE CSV FILE
vikas,gadhi,mumbai,maharashtra
prem,yogi,kolkata,maha
roja,goal,orissa,oya
ram,kala,goa,barka
Issue is How do I fetch all the data(surname,city,state) of user prem into above textboxes studentsurname,studentcity,studentstate from csv file when I search the name in textbox 1 => studentname.Text as prem
Below is the Code where I am stuck at return null and code inside Load_Script_Click
void Connection_fetch_details(String searchName)
{
var strLines = File.ReadLines(filePath);
foreach (var line in strLines)
{
if (line.Split(',')[0].Equals(searchName))
{
Connection_fetch_details cd = new Connection_fetch_details()
{
username = line.Split(',')[1]
};
}
}
return;
}
private void Load_Script_Click(object sender, EventArgs e)
{
// load script is button
String con_env = textenv.Text.ToString();
//Address Address = GetAddress("vikas");
//textsurname.text = Address.Surname
Connection_fetch_details cd = Connection_fetch_details(con_env);
textusername.Text = cd.username;
}
==============================================================
Class file name : Address.class
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace DDL_SCRIPT_GENERATOR
{
public class Connection_fetch_details
{
public string username { get; set; }
}
}
The main problem is that your method is void, which means it doesn't return any value. So even though you may be finding a match, and creating a Connection_fetch_details object, you aren't returning that result back to the calling method.
This will fix that problem:
Connection_fetch_details Connection_fetch_details(String searchName)
{
var strLines = File.ReadLines(filePath);
foreach (var line in strLines)
{
if (line.Split(',')[0].Equals(searchName))
{
Connection_fetch_details cd = new Connection_fetch_details()
{
username = line.Split(',')[1]
};
return cd; //return the object containing the matched username
}
}
return null;
}
Now it will return a Connection_fetch_details object if there is a match, or null if there is no match.
Next, you asked about returning all the fields, not just one. For that you would need to
a) add more properties to your object
b) add more code to populate those properties from the CSV
c) add code to populate the textboxes with the results from the object.
I'm also going to rename "username" to something more relevant, since none of the field names you described in the question match that. I'm also going to rename your class to "Student", and rename your search method, for the same reason.
Here's an example:
Student searchStudent(String searchName)
{
var strLines = File.ReadLines(filePath);
foreach (var line in strLines)
{
var split = line.Split(',');
if (split[0].Equals(searchName))
{
Student s = new Student()
{
firstname = searchName,
surname = split[1],
city = split[2],
state = split[3]
};
return s; //return the object containing the matched name
}
}
return null;
}
private void Load_Script_Click(object sender, EventArgs e)
{
// load script is button
String con_env = textenv.Text.ToString();
//Address Address = GetAddress("vikas");
//textsurname.text = Address.Surname
Student st = searchStudent(con_env);
textsurname.Text = st.surname;
txtcity.Text = st.city;
txtstate.Text = st.state;
}
namespace DDL_SCRIPT_GENERATOR
{
public class Student
{
public string firstname { get; set; }
public string surname { get; set; }
public string city { get; set; }
public string state { get; set; }
}
}
To accomplish your goal you have to further separate your problem in more granular steps and also distinguish between what you show in your UI and what informations you hold in the background in which format.
Create a class with the desired properties
public class Student { public string Name { get; set; } ... }
Learn how to read a csv file into such an object by using an existing library like CsvHelper or CsvReader.
When you have something like List<Student> from this part. Learn how you can visualize such a thing by using some Binding (also depends on the visualization you use Winforms, WPF, etc.).
Depending on the visualization component it already supports filtering or you need to filter by yourself by using e.g. LINQ to get the matching elements students.Where(student => student.Name.StartsWith(search)).
So far a lot of smaller problems which is simply to much to answer in a single one. Please try to break down your problems into smaller ones and search for their solutions. If you get stuck, ask a new question. That's all I can do for you now.
I have certain page having both long (Page1/Page2/MyPage) and simple (MyPage) addresses.
Then I want to reference it in certain place via PropertyUrl:
[CultureSpecific]
[Required]
[BackingType(typeof(PropertyUrl))]
[Display(
Name = "Link",
Description = "Link to the page",
GroupName = SystemTabNames.Content,
Order = 1)]
public virtual Url Link { get; set; }
I want the simple address (if it exists) to be used for the routing or url rendering but not the long one.
I am looking for some elegant solution for it if it exists
Got an answer from Brad McDavid
Modified it a bit to fit better to my task:
public static string GetExternalUrl(this Url url)
{
var content = UrlResolver.Service.Route(new UrlBuilder(url));
return GetExternalUrl(content);
}
public static string GetExternalUrl(this ContentReference contentReference)
{
if (ContentReference.IsNullOrEmpty(contentReference)) return null;
var content = ServiceLocator.Current.GetInstance<IContentLoader>().Get<IContent>(contentReference);
return GetExternalUrl(content);
}
public static string GetExternalUrl(this IContent content)
{
var externalProperty = content?.Property["PageExternalURL"];
return !string.IsNullOrWhiteSpace(externalProperty?.ToString()) ? $"/{externalProperty.ToString().Trim('/')}/" : null;
}
I'm currently trying to implement a Dropdown List with what I would assume is hardcoded values. Basically what I want is to have a Dropdown List with a choice of three possible values.
I have a total of 4 controllers and views that will be using this dropdown. I've seen a lot of examples for MVC2 and MVC3 where people have hard coded their dropdowns in their views, and I personally don't prefer to go with a quick and "dirty" fix such as that.
I have a model containing the following.
public class Status
{
public int id { get; set; }
public string status { get; set; }
public Status(int statusId, string statusName)
{
id = statusId;
status = statusName;
}
}
The status should be able to have any of the 3 possible values:
Active
Inactive
Processing
I thought of creating the status' using this method I currently have in my status class:
public static List<Status> getAllStatus()
{
List<Status> states = new List<Status>();
states.Add(new Status(1, "Active"));
states.Add(new Status(2, "Inactive"));
states.Add(new Status(3, "Processing"));
return states;
}
I haven't been able to figure out how to use this model inside my Controllers alongside with how to pass it along to my views and was hoping someone in here would known how to do that?
EDIT1:
I guess I forgot to mention that I will be storing the selected value as a string in my database and that I am using a view which doesn't have the model of my status class, but rather the model of object which I will be storing in my database (which might be the case of a vehicle object).
EDIT2:
I have a model called Customer, which has some of the following values:
public int CustomerID { get; set }
public string Email { get; set }
public string Phone { get; set }
public Status Status { get; set; }
In my DB for my Customer model I have a string in which I wan to store the selected Status.
So basically I wan't to change the following to a dropdown with 3 options, Inactive, Active and Processing.
However I don't want to code this in my view as I will be needing it in 8 different views and copy pasting that is not very sleek code.
#Html.DropDownListFor(m => m.status_id, new SelectList(getAllStatus(), "id", "status"))
It doesn't make much sense to save it as a string within your database as it sounds more like something static. So u should consider an Enum. To me more precise look to my previous answer and add those Model properties to a ViewModel.
public class CustomerViewModel () {
public int SelectedStatusId { get; set; }
[DisplayName("Status")]
public IEnumerable<SelectListItem> StatusItems
{
get
{
yield return new SelectListItem { Value = "", Text = "- Select a status -" };
StatusTypeEnum[] values = (StatusTypeEnum[])Enum.GetValues(typeof(StatusTypeEnum));
foreach (StatusTypeEnum item in values)
{
if (item != StatusTypeEnum.Unknown)
{
yield return new SelectListItem { Value = ((int)item).ToString(), Text = item.GetDescription() };
}
}
}
}
}
Pass this into your View through your controller:
public class CustomerCOntroller(){
public ActionResult Index(){
CustomerViewModel viewModel = new CustomerViewModel();
return View(viewModel);
}
}
And you are done. If u are more working with a list which u need to build up add it to your viewModel object.
Greetings,
S..
To start you have a lot of vague questions. Be more specific if you can. If you don't know how MVC works that well I would recomment to follow some tutorials on it.
Model.cs (A ViewModel is preferred). You Should create a ViewModel which you passes to the View. Below is an example how to get a list of items.
public int SelectedStatusId { get; set; }
[DisplayName("Status")]
public IEnumerable<SelectListItem> StatusItems
{
get
{
yield return new SelectListItem { Value = "", Text = "- Select a status -" };
StatusTypeEnum[] values = (StatusTypeEnum[])Enum.GetValues(typeof(StatusTypeEnum));
foreach (StatusTypeEnum item in values)
{
if (item != StatusTypeEnum.Unknown)
{
yield return new SelectListItem { Value = ((int)item).ToString(), Text = item.GetDescription() };
}
}
}
}
StatusTypeEnum.cs
public enum StatusTypeEnum()
{
[Description("Active")] // For correct naming
Active,
Inactive,
Processing
}
View.cshtml
#Html.DropDownListFor(x => Model.SelectedStatusId, Model.StatusItems)
EnumAttribute.cs (To read the Annotation Descriptions. And don't try to understand this. It's just magic. It gets the DataAnnotation of the enum types by reflection.)
public static class EnumAttribute
{
public static string GetDescription<TEnum>(this TEnum value)
{
var fi = value.GetType().GetField(value.ToString());
if (fi != null)
{
var attributes = (DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute), false);
if (attributes.Length > 0)
{
return attributes[0].Description;
}
}
return value.ToString();
}
}
You could declare States as public propery in your class and use this to access it in your views:
<ComboBox Grid.Column="1" Grid.Row="0" Margin="5"
VerticalAlignment="Center" ItemsSource="{Binding States}"
IsTabStop="False"}"/>
I tried to search but cannot solve my problem.
This is my controller :
public JsonResult Index()
{
return this.Json(TempData["displayList"], JsonRequestBehavior.AllowGet);
}
public JsonResult AddToCart(string id)
{
QuotationModels objQuote = new QuotationModels();
List<QuotationModels> listQuote = objQuote.GetObjectInSession;
int itemID = Int32.Parse(id);
int index = -1;
if(listQuote != null)
index = listQuote.FindIndex(p => p.ItemdID== itemID);
if (index >= 0)
{
listQuote[index].ProductQty++;
objQuote.AddToSession(listQuote);
}
else
{
int _id = Convert.ToInt16(id);
var _product = DataContext.DataContext.Items.FirstOrDefault(s => s.ID == _id);
QuotationModels quote = new QuotationModels();
quote.ItemdID = _product.ID;
quote.ItemNote = _product.Notes;
quote.Phone = "";
quote.PictureName = _product.PictureName;
quote.ProductName = _product.Name;
quote.ProductPrice = (decimal)_product.Price;
quote.ProductQty = 1;
quote.ShoppingCartId = "";
quote.Total = 0;
quote.Email = "";
quote.CustomerID = 0;
quote.CusName = "";
quote.Company = "";
quote.Address = "";
objQuote.AddToSession(quote);
}
int itemInSession = objQuote.GetObjectInSession.Sum(s => s.ProductQty);
TempData["displayList"] = objQuote.GetObjectInSession;
return Json(new
{
ja = itemInSession
}, JsonRequestBehavior.AllowGet);
}
But when I browse the Index() view, It was an error A circular reference was detected while serializing an object of type.
Can any one give me the solution please. Thank you so much.
I'm not sure what you're trying to serialize, but here is a clue about what you have to do !
The problem of the circular reference means that you have for exemple a Quote, which contains a reference to a Product. And that that Product itsel has a reference to the parent Quote.
You can't serialize that simply in JSON, cause it would do something like this:
Quote :
- some attributes..
- Product
- some attributes
- Quote
- some attributes...
- Product... and so on !
But now, if you have the parent Quote, is it really interesting for you to have the relationship on the child entity ? Maybe in your server-side model, but it's kind of redundant and not necessary for the client.
What you could do in that case is create other classes which don't contain what is not necessary and could result in circular reference.
You'll have for example a SimpleQuote, which is like a Quote, but instead of having a Product property, it will have a SimpleProduct property.
Original classes :
public class Quote{
public int Id;
public Product Product;
public double Amount;
}
public class Product{
public int Id;
public Quote Quote;
public string Name;
}
Simple classes for serialization :
public class SimpleQuote{
public int Id;
public SimpleProduct Product;
public double Amount;
}
public class SimpleProduct{
public int Id;
public int QuoteId;
public string Name;
}
Now you can create extensions methods like :
public static void ToSimpleQuote(this Quote quote){
return new SimpleQuote(){
Id = quote.Id,
Amount = quote.Amount,
Product = quote.Product.ToSimpleProduct()
};
}
public static void ToSimpleProduct(this Product product){
return new SimpleProduct(){
Id = product.Id,
Name = product.Name,
QuoteId = product.Quote.QuoteID
};
}
So if you had something like :
public ActionResult Index(){
....
return Json(myQuote, JsonRequestBehavior.AllowGet);
}
you can now do this instead :
public ActionResult Index(){
....
return Json(myQuote.ToSimpleQuote(), JsonRequestBehavior.AllowGet);
}
Don't return this. Instead use:
public JsonResult Index()
{
return Json(TempData["displayList"], JsonRequestBehavior.AllowGet);
}
Can you show the object graph of what is in TempData["displayList"]?
You might have a looping hierarchy.
You can use the attributes XMLIgnore for strict XML Serializing or NonSerialized for broader targets.
Simply mark the properties or fields that are circular with either of these attributes and it should ignore them.
Works well in Entity Framework scenarios with virtual members properties that are indeed circular references.
I have tried so many combinations, but cannot get the validation to turn off on this code block
[ValidateInput(false)]
public ActionResult aSavePageCopy()
{
aLoggedIn();
int id = Convert.ToInt32(Request.Form["id"]);
PagesDataContext pdc = new PagesDataContext();
Page p = pdc.Pages.Single(row => row.ID == id);
p.PageCopy = Request.Form["PageCopy"];
pdc.SubmitChanges();
return Redirect("/Admin/aViewPages");
}
It seems that this works for others so I don't see what I'm missing here. The error I get is A potentially dangerous Request.Form value was detected from the client
You could use FormCollection which is safe to access instead of Request.Form (but please don't use it, see below for the real solution to your problem):
[ValidateInput(false)]
public ActionResult aSavePageCopy(FormCollection fc)
{
aLoggedIn();
int id = Convert.ToInt32(fc["id"]);
PagesDataContext pdc = new PagesDataContext();
Page p = pdc.Pages.Single(row => row.ID == id);
p.PageCopy = fc["PageCopy"];
pdc.SubmitChanges();
return Redirect("/Admin/aViewPages");
}
Of course that's an absolutely ridiculous and lousy way to solve the problem. The correct way to do it is to use a view model (of course):
public class MyViewModel
{
public int Id { get; set; }
public string PageCopy { get; set; }
}
and then:
[ValidateInput(false)]
public ActionResult aSavePageCopy(MyViewModel model)
{
aLoggedIn();
PagesDataContext pdc = new PagesDataContext();
Page p = pdc.Pages.Single(row => row.ID == model.Id);
p.PageCopy = model.PageCopy;
pdc.SubmitChanges();
return Redirect("/Admin/aViewPages");
}
or if you are using ASP.NET MVC 3 and wanted to disable validation only for a single property on your view model instead of doing it for the entire request you could decorate this view model property with the [AllowHtml] attribute:
public class MyViewModel
{
public int Id { get; set; }
[AllowHtml]
public string PageCopy { get; set; }
}
and then you no longer need the [ValidateInput(false)] attribute on your action:
public ActionResult aSavePageCopy(MyViewModel model)
{
aLoggedIn();
PagesDataContext pdc = new PagesDataContext();
Page p = pdc.Pages.Single(row => row.ID == model.Id);
p.PageCopy = model.PageCopy;
pdc.SubmitChanges();
return Redirect("/Admin/aViewPages");
}
Not only that we have solved the problem but as you can see you no longer need to write any plumbing code in your controller action parsing around integers and stuff which is the role of the model binder.