ASP.NET Mvc Question - asp.net-mvc

I wrote something like this in the controller.
public ActionResult Giris()
{
ViewData["Tarif"] = (from t in _entities.Tarif
join k in _entities.Kullanici on t.KID equals k.KID
select new {KAdi = k.KAdi, TAdi = t.TAdi})
.Take(4);
return View();
}
I am using it as below in the view page.
<% foreach (var item in (IEnumerable<dynamic>)ViewData["Tarif"]) { %>
<div class="begenilen-video" style="float:left">
<img class="video-resmi" alt="reklam" src="../../Uygulama/Resimler/Reklam/1.jpg" />
<span class="benzer-yemek-tarifi-adi"></span><%=item.TAdi %><br />
<span class="benzer-yemek-tarifi-ekleyen">Ekleyen: </span><br />
<span class="benzer-yemek-tarifi-izlenme">İzlenme: </span>
</div>
<% } %>
However,I am receive the error in the select statement.How do I invoke the items in the view page?
Thanks in advance.

As a guess because you haven't posted the error:
The object being stored in ViewData["Tarif"] will be of the type IQueryable<T> where T is an anonymous object and in your view you are casting to IEnumerable<dynamic>. IQueryable is also lazily loaded so you will be trying to execute your query once the object has been disposed.
You should really create a strongly typed view model
public class ViewModelType {
public IEnumerable<TarifType> Tarif { get; set; }
}
Tarif type
public class TarifType {
public string KAdi { get; set; }
public string TAdi { get; set; }
}
controller
public ActionResult Giris() {
var viewModel = new ViewModelType();
viewModel.Tarif = (from t in _entities.Tarif
join k in _entities.Kullanici on t.KID equals k.KID
select new TraifType { KAdi = k.KAdi, TAdi = t.TAdi }
).Take(4)
.ToList();
return View(viewModel);
}
view
<% foreach (var item in viewModel.Tarif) { %>
<div class="begenilen-video" style="float:left">
<img class="video-resmi" alt="reklam" src="../../Uygulama/Resimler/Reklam/1.jpg" />
<span class="benzer-yemek-tarifi-adi"></span><%=item.TAdi %><br />
<span class="benzer-yemek-tarifi-ekleyen">Ekleyen: </span><br />
<span class="benzer-yemek-tarifi-izlenme">İzlenme: </span>
</div>
<% } %>

Related

Asp.net core MVC fetch image from DB based on the Category

I am sorry to bother with simple matters but i really cannot find a way out of this problem.
I am building a Gallery, which container different fields, one of those is Category.
Category Class is a public Enum, and i would like to retrieve all the images in the Database and display them in View based on my Category selection.
Here you can find the code that i wrote so far.
View:
<form method="get" asp-controller="Gallery" asp-action="index">
<div style="height:60px;" class="container">
<div class="row">
<div class="col-md-5">
<div class="row" style="padding-top:10px;">
<div class="col-md-5">
#Html.Editor("Name", new { htmlAttributes = new { #class = "form-control", placeholder = "Name..." } })
</div>
</div>
</div>
<div class="col-md-5">
<select class="custom-select form-control mr-sm-2" asp-items="Html.GetEnumSelectList<Category>()"></select>
</div>
<div class="col-md-1">
<div class="row" style="padding-top:10px; padding-right:20px;">
<button type="submit" name="submit" class="btn btn-success form-control" value="submit">
<i class="fas fa-search fa-1x"></i>
</button>
</div>
</div>
</div>
</div>
</form>
Controller:
public IActionResult Index(string Name, Category category)
{
var model = _galleryRepository.GetAllImages();
StringBuilder param = new StringBuilder();
param.Append("&Name=");
if (Name != null)
{
param.Append(Name);
}
if(Name != null)
{
model = _galleryRepository.SearchName(Name);
}
if(category != Category.All)
{
model = _galleryRepository.SearchCategory(category);
}
return View(model);
}
Model Category:
public enum Category
{
All,
Photography,
Portrait,
Nature
}
Model Gallery:
public class Gallery
{
public int Id { get; set; }
public int Like { get; set; }
public string Comment { get; set; }
[Required]
[MaxLength(40, ErrorMessage ="Name cannot exceed 40 characters")]
public string Name { get; set; }
[Required]
[MaxLength(100, ErrorMessage = "Description cannot exceed 100 characters")]
public string Description { get; set; }
[Required]
public Category Category { get; set; }
public string PhotoPath { get; set; }
}
I did Managed to create a search form based on the Name of the image and it works just fine. But when it come to retrieve the images based on the Category Selection, it does not work.
i used a breakpoint on the Controller on the If statment related to category, and i realized that the condition fires but the model inside no.
So i am asking to the expert for an explanation about how to fix it as it the first time that i work with Enum and retrieving datas based on Enum classes.
Thank you so much for your help and i hope i made clear my problem.
Change your view like below,then you could pass the selected item to category:
#model Gallery
<form method="get" asp-controller="Gallery" asp-action="index">
//...
<div class="col-md-5">
<select asp-for="Category" class="custom-select form-control mr-sm-2" asp-items="Html.GetEnumSelectList<Category>()"></select>
</div>
//...
</form>
The default model binder won't work with Enum types. Either you need to change the parameter to of type string and convert it to it's equivalent enum type before performing the comparisions OR provide your own implementation of model binder and override the default one. If I were you, I will go with the simplest solution like below,
public IActionResult Index(string Name, string selectedCategory)
{
var category = Enum.Parse(typeof(Category),selectedCategory,true);
var model = _galleryRepository.GetAllImages();
StringBuilder param = new StringBuilder();
param.Append("&Name=");
if (Name != null)
{
param.Append(Name);
}
if(Name != null)
{
model = _galleryRepository.SearchName(Name);
}
if(category != Category.All)
{
model = _galleryRepository.SearchCategory(category);
}
return View(model);
}

asp.net mvc viewmodel getting error public definition for getenumerator

I can get my Products model to my view ok. but I need to pass it in a ViewModel so I can interact with data from several models. When I bind my view to ProductPageViewModel then I get the "no public definition for GetEnumerator" error. I have tried all manner of IEnumerable options and cannot find the right combination.
I included controller and view that work when the view is bound to the model.
The full error is
CS1579: foreach statement cannot operate on variables of type JaniesWebLive.ViewModel.ProductPageViewModel' because
JaniesWebLive.ViewModel.ProductPageViewModel' does not contain a public definition for 'GetEnumerator'
Triggered at #foreach (var item in Model)
Products.cs
public class Products
{
[Key]
public int WpId { get; set; }
public string Category { get; set; }
public string WpProductId { get; set; }
public string ProdDescShort { get; set; }
public string ProdDescLong { get; set; }
public string ProductMedium { get; set; }
public decimal? Price1 { get; set; }
}
ProductPageViewModel.cs
public class ProductPageViewModel
{
public IEnumerable<Products> Products { get; set; }
public Contact Contacts { get; set; }
public string Message { get; set; }
/*more models to be added */
}
ProductsController.cs
public class ProductsController : Controller
{
private ApplicationDbContext db = new ApplicationDbContext();
public ActionResult ShortList(string prodname)
{
var products = db.DbProducts.Where(m => m.Category == "homepage");
var model = new ViewModel.ProductPageViewModel
{
Products = products,
Message = "Thanks for your business! "
/* more models to be added */
};
return View(model);
}
}
ShortList.cshtml
#model IEnumerable<JaniesWebLive.ViewModel.ProductPageViewModel>
#foreach (var item in Model)
{
<div class="row">
<div class="col-md-4 col-sm-6 col-xs-12">
<p><img class="product-image" src=#Html.DisplayFor(modelItem => item.ProductMedium) /></p><br />
<h3>#Html.DisplayFor(modelItem => item.WpProductId)</h3>
<h5>#Html.DisplayFor(modelItem => item.Price1)</h5>
<h6>#Html.DisplayFor(modelItem => item.ProdDescShort)</h6>
<p class="text-center">#Html.DisplayFor(modelItem => item.ProdDescLong)</p>
<p>
<button class="text-right btn btn-link">SHORT LIST</button>
</p>
</div>
</div>
}
Working controller and view
public ActionResult LongList(string prodname)
{
var model = db.DbProducts.Where(m => m.Category == "homepage");
return View(model);
}
LongList.cshtml
#model JaniesWebLive.Models.Products
#foreach (var item in Model)
{
<div class="row">
<div class="col-md-4 col-sm-6 col-xs-12">
<p><img class="product-image" src=#Html.DisplayFor(modelItem => item.ProductMedium) /></p>
<h3>#Html.DisplayFor(modelItem => item.WpProductId)</h3>
<h5>#Html.DisplayFor(modelItem => item.Price1)</h5>
<h6>#Html.DisplayFor(modelItem => item.ProdDescShort)</h6>
<p class="text-center">#Html.DisplayFor(modelItem => item.ProdDescLong)</p>
<p>
<button class="text-right btn btn-link">LONG LIST</button>
</p>
</div>
</div>
}
you need to change the view to something like
#model JaniesWebLive.ViewModel.ProductPageViewModel
#foreach (var item in Model.Products )
{
<div class="row">
<div class="col-md-4 col-sm-6 col-xs-12">
<p><img class="product-image" src=#Html.DisplayFor(modelItem => item.ProductMedium) /></p><br />
<h3>#Html.DisplayFor(modelItem => item.WpProductId)</h3>
<h5>#Html.DisplayFor(modelItem => item.Price1)</h5>
<h6>#Html.DisplayFor(modelItem => item.ProdDescShort)</h6>
<p class="text-center">#Html.DisplayFor(modelItem => item.ProdDescLong)</p>
<p>
<button class="text-right btn btn-link">SHORT LIST</button>
</p>
</div>
</div>
}
since upr view model is a single object which contain a list property you need to itterate the property not the whole model

MVC5 ActionResult model being passed as empty

I have read plenty of posts about this issue but I can't seem to find a solution that fits with my implementation. I'm giving MVC another attempt (I'm a webforms guy). The model being passed to my ActionResult is basically empty when it should be populated. I'm starring at the sample that works and I can find no differences. It seems to be something impossible to debug too. Any pointers will be greatfully appreciated.
View:
#model WebApplication1.Models.SiteViewModel
#{
ViewBag.Title = "Delete your site";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<p>Are you sure you want to delete this site?</p>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(false)
<ul class="list-group">
<li class="list-group-item">
<div class="row">
<div class="col-md-2"><b>#Html.LabelFor(model => model.Name)</b></div>
<div class="col-md-6">#Model.Name</div>
</div>
</li>
<li class="list-group-item">
<div class="row">
<div class="col-md-2"><b>#Html.LabelFor(model => model.Phase)</b></div>
<div class="col-md-6">#Model.Phase</div>
</div>
</li>
<li class="list-group-item">
<div class="row">
<div class="col-md-2"><b>#Html.LabelFor(model => model.Type)</b></div>
<div class="col-md-6">#Model.Type</div>
</div>
</li>
</ul>
<button type="submit" class="btn btn-danger">Delete</button>
#Html.ActionLink("Back to List", "Index", null, new { #class = "btn btn-default" })
}
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
Model:
public class SiteViewModel
{
public SiteViewModel()
{
Services = new List<ServiceModel>();
}
public SiteViewModel(SiteModel site)
{
this.SiteId = site.SiteId;
this.Name = site.Name;
this.Type = site.Type;
this.Phase = site.Phase;
this.Services = site.Services;
}
public int SiteId { get; set; }
[Required(ErrorMessage = "Name is required")]
public string Name { get; set; }
public SchoolType Type { get; set; }
public SchoolPhase Phase { get; set; }
public DateTime? Deleted { get; set; }
public virtual ICollection<ServiceModel> Services { get; set; }
}
Controller Action:
[HttpPost]
public ActionResult Delete(SiteViewModel model)
{
var site = siteRepository.GetById(model.SiteId);
if (site == null) { throw new ArgumentException(string.Format("Site with Id [{0}] does not exist", model.SiteId)); }
try
{
siteRepository.SoftDeleteAndSubmit(site);
base.SetSuccessMessage("The site has been (soft) deleted.");
return RedirectToAction("Index");
}
catch (Exception ex)
{
base.SetErrorMessage("Whoops! Couldn't delete the site. The error was [{0}]", ex.Message);
}
return View(model);
}
Thanks,
Chris.
If you want a fully-populated model you'll need to use form elements or the form helper functions to post your data.
#using(Html.BeginForm())
{
<input type="text" value="#Model.Name" />
// or
Html.TextBoxFor(m => m.Name)
...
}
The example you linked relies on a URL routing rule to match a model's parameter. So you need to rename SiteId to Id or add/modify a routing rule.
If you only need the id then I would just pass that parameter as it will make your intent more obvious and is less prone to breaking.
#using(Html.BeginForm())
{
#Html.HiddenFor(m => m.Id)
<button type="submit">Delete</button>
}
[HttpPost]
public ActionResult Delete(int id)
{
var site = siteRepository.GetById(id);
...
}

MVC How to reaction to 2 different methods in one page

I have 2 methods : Add and Subtract. I want that when clicked Add button, the 3rd textbox displays the result of A + B; clicked "Subtract" button, the 3rd textbox displays the result of A - B.
I thought it should be a simple thing to do (because it can be done within a few lines of code in ASP.NET WebForm Application). But after trying many times and asked a few of friends, I still cannot find the solution...
#using (Html.BeginForm("Add", "MyMVC"))
{
<ol>
<li>
#Html.TextAreaFor(m => m.A)
</li>
<li><span>+ </span></li>
<li>
#Html.TextAreaFor(m => m.B)
</li>
<li><span>= </span></li>
<li>
#Html.TextAreaFor(m => m.C)
</li>
</ol>
#{
Html.RenderAction("Calculate", "MyMVC");
}
#{
Html.RenderAction("Subtract", "MyMVC");
}
}
The RenderAction tags aren't needed. The BeginForm extension also needs to render a form element that posts to itself.
Change your view to
#model SampleMvc.Models.SumModel
#using (Html.BeginForm())
{
<ol>
<li>
#Html.TextAreaFor(m => m.A)
</li>
<li><span>+ </span></li>
<li>
#Html.TextAreaFor(m => m.B)
</li>
<li><span>= </span></li>
<li>
#Html.TextAreaFor(m => m.C)
</li>
</ol>
<input type="submit" id="add" name="Calculate" value="Add" />
<input type="submit" id="subtract" name="Calculate" value="Subtract" />
}
Notice the name attribute on the submit inputs, this will enable the default model binder to bind to a property called Calculate.
For you View model use something similar to
public class SumModel {
public int A { get; set; }
public int B { get; set; }
public int C { get; private set; }
public string Calculate { get; set; }
public void RunCalculation() {
if (Calculate.Equals("add",StringComparison.InvariantCultureIgnoreCase)) {
C = A + B;
} else {
C = A - B;
}
}
}
Then in the controller have actions similar to:
public ActionResult Calculate() {
return View();
}
[HttpPost]
public ActionResult Calculate(SumModel sumModel) {
sumModel.RunCalculation();
return View(sumModel);
}
When the form is submitted via the click events on the submit inputs the value of the button will be auto-magically bound to the Calculate property of the SumModel.
Then when the method RunCalculation is called it uses the property to work out which operation to run against the values A and B
Other easy approach is , you can have the same name for the buttons. and then read it in controller.
<input type="submit" id="add" name="buttonclicked" value="Add" />
<input type="submit" id="subtract" name="buttonclicked" value="Subtract" />
[HttpPost]
public ActionResult Index(string buttonclicked, SumModel sumModel) {
if(buttonclicked=="add"){
}
else{
}
}

How do I post two instances of the same property from a view to an action?

How can I send my data from form, two fields are the same: Station name, but they have different values. How send they via post method to controller. Asp.net mvc2
here what i try:
<% using (Html.BeginForm("ViewRes", "Shedule"))
{%>
<%= Html.ValidationSummary(true) %>
<fieldset>
<legend>Поиск по расписанию:</legend>
<ul>
<li>Из<%= Html.EditorFor(model => model.StationName) %></li>
<li>В<%= Html.EditorFor(model1 => model1.StationName) %></li>
<li>Дата отправления</li>
</ul>
<p>
<input type="submit" value="OK" />
</p>
</fieldset>
<% } %>
and such controller:
[HttpPost]
public ActionResult ViewRes(string a1, string b1)
{
DateTime dtm = Convert.ToDateTime("30.11.2011 0:00:00");
var res = (from d in db.RouteDetail
from m in db.RouteDetail
lalala
where (d.Station == a1
&&
m.Station == b1)
lalalal
}).ToList();
return View(res);
}
The way I would approach this is to refactor my model to encompass both of your existing inputs separately. That way each can be bound accordingly in the action.
public class RailwayRoute
{
public string StartStation { get; set; }
public string EndStation { get; set; }
}
View
<% using (Html.BeginForm("ViewRes", "Shedule"))
{%>
<%= Html.ValidationSummary(true) %>
<fieldset>
<legend>Поиск по расписанию:</legend>
<ul>
<li>Из<%= Html.EditorFor(model => model.StartStation) %></li>
<li>В<%= Html.EditorFor(model => model.EndStation) %></li>
<li>Дата отправления</li>
</ul>
<p>
<input type="submit" value="OK" />
</p>
</fieldset>
<% } %>
Controller/Action
[HttpPost]
public ActionResult ViewRes(string startStation, string endStation)
{
...
}
Expanding on tvanfosson's answer which pretty much sums up, I would try and decouple your data model from your view data. This is often done by using the MVVMC aproach where VM stands for view model. In your case you appear to be passing directly the data model to the view which is sometimes not the recommended approach.
So changing tvanfosson's RailwayRoute to a viewModel object I would ensure the controller action maps the data appropiately. Something like
[HttpPost]
public ActionResult ViewRes(RailwayRouteViewModel viewModel)
{
DateTime dtm = Convert.ToDateTime("30.11.2011 0:00:00");
var res = (from d in db.RouteDetail
from m in db.RouteDetail
lalala
where (d.Station == viewModel.StartStation
&&
m.Station == viewModel.EndStation)
lalalal
select new RailywayRouteViewModel()
{
StartStation = d.Station,
EndStation = m.Station
}
}).ToList();
return View(res);
}

Resources