assign list items to model properties - asp.net-mvc

MODEL
namespace CG.MyPollSurveyAdmin.Models
{
public class CompletePollSurvey
{
public long PollSurveyID { get; set; }
public string Name { get; set; }
public List<OptionData> Options { get; set; }
public List<QuestionData> QuestionDetails { get; set; }
}
public class QuestionData
{
public string QuestionName { get; set; }
public long QuestionID { get; set; }
public int OptionID { get; set; }
public string OptionType { get; set; }
public string Option_1 { get; set; }
public string Option_2 { get; set; }
public string Option_3 { get; set; }
public string Option_4 { get; set; }
public string Option_5 { get; set; }
}
}
CONTROLLER
private List<Question> GetQuestionsById(long PollSurveyId)
{
MemoryStream outMemoryStream = RESTFulServiceHelper.Instance.ExecuteGetMethod(Constants.Method_GetAllQuestions, Convert.ToString(Session[Constants.NTLoginID]));
DataContractJsonSerializer outDataContractJsonSerialize = new DataContractJsonSerializer(typeof(List<Question>));
List<Question> lstQuestions = outDataContractJsonSerialize.ReadObject(outMemoryStream) as List<Question>;
List<Question> question = lstQuestions.Where(p => p.PollSurveyID == PollSurveyId).ToList();
return question;
}
public ActionResult Help(long PollSurveyID=2)
{
if (Session[Constants.Session_IsAdmin] != null && Convert.ToBoolean(Session[Constants.Session_IsAdmin]))
{
CompletePollSurvey completePollSurvey = new CompletePollSurvey();
List<Question> question = GetQuestionsById(Convert.ToInt64(PollSurveyID));
return View(completePollSurvey);
}
else
{
return RedirectToAction("Login");
}
}
Here is the model and controller of my program. Till now I'm getting All the questions for poll id=2 but I'm having difficulty in retrieving element from Question List and assign it to Model List elements(or list to list assignment).
For e.g I have 5 questions for Poll=2 and in each question there are 5 options

Related

AutoMapper Many to Many relationship

I'm not sure where I'm going wrong here. I want to map my classes so that there aren't extra levels in the returned values.
Models (DTOs):
public class FilmViewModel
{
public FilmViewModel() { }
public int Id { get; set; }
[Required(ErrorMessage = "Naziv filma je obavezno polje.")]
public string Naziv { get; set; }
public string Opis { get; set; }
public string UrlFotografije { get; set; }
[RegularExpression(#"^(19|20)[\d]{2,2}$", ErrorMessage = "Godina mora biti u YYYY formatu.")]
public int Godina { get; set; }
public JezikEnum Jezik { get; set; }
public int Trajanje { get; set; }
public bool IsActive { get; set; }
public List<Licnost> Licnosti { get; set; }
}
public class LicnostViewModel
{
public LicnostViewModel() { }
public int Id { get; set; }
[Required]
public string ImePrezime { get; set; }
[Required]
public bool IsGlumac { get; set; }
[Required]
public bool IsRedatelj { get; set; }
public List<Film> Filmovi { get; set; }
}
Entities:
public class Film
{
[Key]
public int Id { get; set; }
[Required]
public string Naziv { get; set; }
public string Opis { get; set; }
public string UrlFotografije { get; set; }
[RegularExpression(#"^(19|20)[\d]{2,2}$")]
public int Godina { get; set; }
public JezikEnum Jezik { get; set; }
public bool IsActive { get; set; }
public int Trajanje { get; set; }
public List<FilmLicnost> Licnosti { get; set; }
}
public class Licnost
{
[Key]
public int Id { get; set; }
[Required]
public string ImePrezime { get; set; }
[Required]
public bool IsGlumac { get; set; }
[Required]
public bool IsRedatelj { get; set; }
public List<FilmLicnost> Filmovi { get; set; }
}
public class FilmLicnost
{
[Key]
public int Id { get; set; }
[ForeignKey(nameof(Licnost))]
public int LicnostId { get; set; }
public Licnost Licnost { get; set; }
[ForeignKey(nameof(Film))]
public int FilmId { get; set; }
public Film Film { get; set; }
}
Basically Swagger already shows me what I'm returning, but I want to avoid unnecessary nesting. It's marked in the image:
I want to say that I've been looking all over SO, AutoMapper documentation etc. No answer/example finds me the solution I need. I'm either missing a Model(DTO) somewhere or there is something major wrong with my logic.
Some example links that I tried are this and this
Also here are some links I tried to get information from: link1, link2
This is what I've tried so far:
CreateMap<FilmLicnost, LicnostViewModel>()
.ForMember(dest => dest.Filmovi, dest => dest.MapFrom(x => x.Film))
.AfterMap((source, destination) =>
{
if (destination?.Filmovi == null) return;
foreach (var temp in destination.Filmovi)
{
temp.Id = source.Film.Id;
temp.IsActive = source.Film.IsActive;
temp.Jezik = source.Film.Jezik;
temp.Naziv = source.Film.Naziv;
temp.Opis = source.Film.Opis;
temp.Godina = source.Film.Godina;
temp.Trajanje = source.Film.Trajanje;
temp.UrlFotografije = source.Film.UrlFotografije;
}
});
CreateMap<FilmLicnost, FilmViewModel>()
.ForMember(dest => dest.Licnosti, dest => dest.MapFrom(x => x.Licnost))
.AfterMap((source, destination) =>
{
if (destination?.Licnosti == null) return;
foreach (var temp in destination?.Licnosti)
{
temp.Id = source.Licnost.Id;
temp.ImePrezime = source.Licnost.ImePrezime;
temp.IsGlumac = source.Licnost.IsGlumac;
temp.IsRedatelj = source.Licnost.IsRedatelj;
}
});
Also this:
CreateMap<FilmLicnost, Film>()
.ForMember(dest => dest.Licnosti, dest => dest.Ignore());
CreateMap<FilmLicnost, Licnost>()
.ForMember(dest => dest.Filmovi, dest => dest.Ignore());
Note I have already defined the mapping for Entities:
CreateMap<Film, FilmViewModel>();
CreateMap<FilmViewModel, Film>();
CreateMap<Licnost, LicnostViewModel>();
CreateMap<LicnostViewModel, Licnost>();

ASP.NET MVC Check if User has already posted in this table

I'm gonna cut to the chase.
I'm creating a Survey platform, it has 3 models.
Model Survey, it has Many SurveyQuestion which has many SurveyAnswer.
(I can insert all of the values of these models but I dont think it is needed)
public class SurveyAnswer
{
[Key]
public int Id { get; set; }
public string Value { get; set; }
public string SubmittedBy { get; set; }
public int SurveyId { get; set; }
public int QuestionId { get; set; }
public virtual Survey Survey { get; set; }
public virtual SurveyQuestion Question { get; set; }
public string Comment { get; set; }
}
Now a problem I'm having is once someone created a survey and another person is starting it, he answers and that's it. How do I show that the next time he comes to an index page? How do I show that "you already submitted this survey"? Do I do that in Controller or in View? I would prefer to that in this action currently (it's a menu for all ongoing surveys).
[HttpGet]
public ActionResult Menu()
{
var survey = Mapper.Map<IEnumerable<Survey>, IEnumerable<SurveyViewModel>>(_unitOfWork.SurveyRepository.Get());
return View(survey.ToList());
}
Put all your validation rules to your AbstractValidator class.
[Validator(typeof(SurveyAnswerValidator))]
public class SurveyAnswer{
[Key]
public int Id { get; set; }
public string Value { get; set; }
public string SubmittedBy { get; set; }
public int SurveyId { get; set; }
public int QuestionId { get; set; }
public virtual Survey Survey { get; set; }
public virtual SurveyQuestion Question { get; set; }
public string Comment { get; set; }
}
public class SurveyAnswerValidator : AbstractValidator<SurveyAnswer>
{
public SurveyAnswerValidator()
{
//list your rules
RuleFor(x => x.SubmittedBy).Must(BeUnique).WithMessage("Already
submitted this survey");
}
private bool BeUnique(string submittedBy)
{
if(_context.SurveyAnswers.
FirstOrDefault(x => x.SubmittedBy == submittedBy) == null){
return true;
}
else{
return false;
}
}
}
If you want to check uniqueness in ViewModel you can use Remote.
public class SurveyAnswerVM{
[Key]
public int Id { get; set; }
public string Value { get; set; }
[Remote("HasSubmitted", "ControllerName")]
public string SubmittedBy { get; set; }
public int SurveyId { get; set; }
public int QuestionId { get; set; }
public virtual Survey Survey { get; set; }
public virtual SurveyQuestion Question { get; set; }
public string Comment { get; set; }
}
Where HasSubmitted is a method you may create in controller to return true if the user has submitted.
RemoteAttribute
https://msdn.microsoft.com/en-us/library/gg508808(VS.98).aspx
The best solution by vahdet (suggested in comments)
[Index("IX_AnswerQuestion", 2, IsUnique = true)]
[StringLength(36)]
public string SubmittedBy { get; set; }
public int SurveyId { get; set; }
[Index("IX_AnswerQuestion", 1, IsUnique = true)]
public int QuestionId { get; set; }

MVC models converting error

How to set to a different model?
List<ORDER_DETAILSMetadata> result = db.ORDER_DETAILS.Where(p => p.Order_Number == id).ToList();
Error 6 Cannot implicitly convert type 'System.Collections.Generic.List<Mvc5.Models.ORDER_DETAILS>' to 'System.Collections.Generic.List<Mvc5.Models.ORDER_DETAILSMetadata>'
ORDER_DETAILSMetadata
MetadataType(typeof(ORDER_DETAILSMetadata))]
public partial class ORDER_DETAILS
{
// Note this class has nothing in it. It's just here to add the class-level attribute.
}
public class ORDER_DETAILSMetadata
{
public int Order_Details_ID { get; set; }
public Nullable<int> Order_Number { get; set; }
public Nullable<short> Sequence_Number { get; set; }
public string Item_Num { get; set; }
public Nullable<short> Order_Quantity { get; set; }
public Nullable<short> Ship_Quantity { get; set; }
}
ORDER_DETAILS.cs
public partial class ORDER_DETAILS
{
public int Order_Details_ID { get; set; }
public Nullable<int> Order_Number { get; set; }
public Nullable<short> Sequence_Number { get; set; }
public string Item_Num { get; set; }
public Nullable<short> Order_Quantity { get; set; }
public Nullable<short> Ship_Quantity { get; set; }
}
As far as i have understood, you can do something like this:
List<ORDER_DETAILSMetadata> result = db.ORDER_DETAILS.
Where(p => p.Order_Number == id).
Select(x => new ORDER_DETAILSMetadata
{
Order_Details_ID = x.Order_Details_ID,
Order_Number = x.Order_Number,
Sequence_Number = x.Sequence_Number,
Item_Num = x.Item_Num,
Order_Quantity = x.Order_Quantity,
Ship_Quantity = x.Ship_Quantity
}).ToList();
If you just want to convert one type of model to other type, you can do something like:
List<target> targetList = new List<target>(originalList.Cast<target>());
You can check the details about Cast() and OfType() here. Go for the first approach when you have different count and types of fields.

MVC model value becomes null on post back

I am getting null value for the model on postback.I am not able to find out where I am going wrong.I have seen similar questions but couldn't find any solution yet.
Here is my code:
Controller:
public ActionResult ContactUpdate(string id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
string[] testsplit = id.Split(',');
List<int> intTest = new List<int>();
foreach (string s in testsplit)
intTest.Add(int.Parse(s));
ObjectParameter ObjParam = new ObjectParameter("ErrorCode", 0);
var cont = db.spErrorContactGet(365, ObjParam);
var ToBeUpdated = (from contacts in cont
where intTest.Contains(contacts.ResponseID)
select contacts);
IEnumerable<spErrorContactGet_Result> Update = ToBeUpdated.ToList();
return View(Update);
}
[HttpPost]
public ActionResult ContactUpdate(List<spErrorContactGet_Result> Res)
{
if (Res == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
//do something
// redirect to another view
}
Here is the model class:
public class spErrorContactGet_Result
{
public int ResponseID { get; set; }
public string ContactAlchemyMessage { get; set; }
public string ContactTeamAlchemyMessage { get; set; }
public string ContactElectronicAddressAlchemyMessage { get; set; }
public string ContactAccountAlchemyMessage { get; set; }
public string CRMContactID { get; set; }
public string InfluenceLevel { get; set; }
public string JobRole { get; set; }
public string Department { get; set; }
public string DepartmentName { get; set; }
public string MobilePhone { get; set; }
public string Email { get; set; }
public string Suffix { get; set; }
public string FaxNumber { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string MiddleName { get; set; }
public string JobTitle { get; set; }
public string HonorablePrefix { get; set; }
public string Prefix { get; set; }
public string ContactAuthPhoneId { get; set; }
public string ContactAuthDmailId { get; set; }
public string ContactAuthEmailId { get; set; }
public string AllowFax { get; set; }
public string PartnerContactAuthPhoneID { get; set; }
public string PartnerContactAuthDmailID { get; set; }
public string PartnerContactAuthEmailID { get; set; }
public string PrivacyStatementReviewed { get; set; }
public string PreferredLanguage { get; set; }
public string IndWorkPhone { get; set; }
public string FullNamePronunciation { get; set; }
public string CRMOwner { get; set; }
public string KeyContact { get; set; }
public string MarketingAudience { get; set; }
public bool IsSelected { get; set; }
}
}
I am unable to post the view in the right format.
It is likely that structure of your view differs from one that is of your model, they must syntactically match. If you would post your view it could help. BTW there is no 'Postback' in MVC

MVC Accessing navigation property for listboxFor

At first I should say i am compeletely newbie in MVC.
I have 3 Objects
public partial class Magazine
{
public Magazine()
{
this.NumberTitles = new HashSet<NumberTitle>();
}
public int Id { get; set; }
public int MagYear { get; set; }
public int MagNo { get; set; }
public int MagSeason { get; set; }
public string MagYear2 { get; set; }
public virtual ICollection<NumberTitle> NumberTitles { get; set; }
}
public partial class NumberTitle
{
public NumberTitle()
{
this.Articles = new HashSet<Article>();
}
public int Id { get; set; }
public int MagazineId { get; set; }
public int TitleId { get; set; }
public int position { get; set; }
public virtual ICollection<Article> Articles { get; set; }
public virtual Magazine Magazine { get; set; }
public virtual Title Title { get; set; }
}
public partial class Title
{
public Title()
{
this.ChildrenTitle = new HashSet<Title>();
this.NumberTitles = new HashSet<NumberTitle>();
}
public int Id { get; set; }
public string TitleText { get; set; }
public Nullable<int> ParentId { get; set; }
public virtual ICollection<Title> ChildrenTitle { get; set; }
public virtual Title ParentTitle { get; set; }
public virtual ICollection<NumberTitle> NumberTitles { get; set; }
}
In a View I want to have TextBox to show Magazine Number and 2 List boxes. one shows all the Available Titles and the Other just selected Titles for that Magazine Number.So I have made View Model
public class NumberTitleViewModel
{
public Magazine Magazine { get; set; }
public List<NumberTitle> NumberTitles { get; set; }
}
this is in controller. how can i get the list of titles for specified MagazineId
public ActionResult EditTitle(int id)
{
Func<IQueryable<Magazine>, IOrderedQueryable<Magazine>> orderByFunc = null;
Expression<Func<Magazine, bool>> filterExpr = null;
if (id>0)
{
filterExpr = p => p.Id.Equals(id);
}
Magazine magazine = unitOfWork.MagazineRepository.Get(filter: filterExpr, orderBy: orderByFunc, includeProperties: "").SingleOrDefault();
NumberTitleViewModel numberTitleViewMode = new NumberTitleViewModel();
numberTitleViewMode.Magazine = magazine;
Expression<Func<NumberTitle, bool>> filterExpr2 = null;
if (id > 0)
{
filterExpr2 = p => p.MagazineId.Equals(id);
}
var numberTitles = unitOfWork.NumberTitleRepository.Get(filterExpr2, null, includeProperties: "Title").ToList();
var titles = unitOfWork.TitleRepository.Get(null, null, "");
numberTitleViewMode.NumberTitles = numberTitles; ///this part doesn't show the Titles. how should access the TitleName not Id
ViewBag.titles = new SelectList(titles, "Id", "TitleText");
return View("../Panel/Magazine/EditTitle", "_BasicLayout", numberTitleViewMode);
}
Not sure what you have in your view but you should have something like:
#using NameSpace.Models
#model NameSpace.Models.NumberTitleViewModel
Then you can do something like this in your view:
foreach (NumberTitles item in #Model)
{
<label>#item.Title.TitleText</label>
}
Not exact but should get you close to what you need

Resources