URL as a concatenated string in ASP.NET MVC View - c#

I am trying to create a custom url which is within a loop so that through each loop the produced url is different. The code looks like this:
#foreach (var car in Model)
{
<div class="container">
#{string country = Html.DisplayFor(modelCar => car.Country).ToString()}
#{string mapUrl = "https://maps.googleapis.com/maps/api/staticmap?zoom=14&size=150x120&key=[insertkey]&center="
+ country}
<img src=#mapUrl />
</div>
}
The problem is the line where I define mapUrlrenders an error. What is the problem with this code?
Thanks in advance.

I think you are simply missing the semi columns for the variables and quotes for the image src tag.
Also i am not sure why you are calling DisplayFor to get the country variable name! DisplayFor returns an MvcHtml string and is usually used to get the encoded html markup to render to browser. Unless you have some crazy overloading of that (why would you do that on DisplayFor ? Use a simply helper method), do not misuse the DisplayFor helper
This should work.
#foreach (var car in Model)
{
<div class="container">
#{ var country = car.Country; } // i assume you just need the Country
#{ var mapUrl = "https://maps.googleapis.com/maps/api/staticmap?zoom=14&size=150x120&key=[insertkey]&center=" + country; }
<img src="#mapUrl" />
</div>
}

Related

Form within a foreach loop not posting the model back to the controller

I've searched around and can't find an answer to my problem.
I've got a View that takes accepts Foo in like so:
#model IEnumerable<MyApplication.Models.Foo>
Inside of the view I've got a table. I populate the the table just doing a simple foreach loop through my Foo model. I have added a column where a user can add details to each row in a text area and save.
So the view looks like this:
#foreach (var item in Model)
{
<tr>
<th>
#using (Html.BeginForm("AddDetails", "MyController", FormMethod.Post))
{
#Html.AntiForgeryToken()
#Html.HiddenFor(u => item.Id)
#Html.TextAreaFor(u => item.Details, new { #class = "form-control" })
<input type="submit" value="Save" class="btn btn-sm btn-default" />
}
</th>
</tr>
}
My controller is setup like this:
[HttpPost]
public ActionResult AddDetails(Foo foo)
{
}
When I set a breakpoint on that controller foo always has null values for the Details property and the Id is always 0. When it's passed into the view it's got all of the properties set to right, so I'm not sure why it is not posting back properly?
I've tried this:
#using (Html.BeginForm("AddDetails", "MyController", FormMethod.Post, new { foo = Model }))
I have also tried removing the foreach loop and changing it to pass in just a single Model to the View and for the View to accept just the single model instead of an IEnumerable. When I do this it posts back just fine.
And that does not work either. I'm wondering if it has something to do with the fact that my form is within a foreach loop and perhaps I need to do a little more work like add a data-id attribute to the element and just capture the click event on the button and do an AJAX call to the controller and pass the right values along that way?
EDIT Sorry I completely forgot the view model. Here is what that looks like:
public class Foo
{
public int Id { get; set; }
public string Details { get; set; }
}
Generally speaking it's bad form to post to a different model than what your form view is composed from. It makes a lot of things difficult, not the least of which is recovering from validation errors.
What you're doing here is looping through a list of Foo and creating multiple forms that will each submit only a single Foo to an action that takes only a single Foo. While the post itself is fine, using the *For helpers on a model that is not the same as what you're posting to will likely not generate the proper input names necessary for the modelbinder to bind the posted values onto that other model. At the very least, if you need to return to this view because of a validation error, you will not be able to keep the user's posted data, forcing them to repeat their efforts entirely.
Ideally, you should either post the entire list of Foo and have just one form that wraps the iteration (in which case, you would need to use for rather than foreach). Or you should simply list the Foos with a link to edit a particular Foo, where you would have a form for just one Foo.
try to do this.possible problems
form should outside the table
single form for whole table
wrap your column editor inside tbody not thead
#using (Html.BeginForm("AddDetails", "MyController", FormMethod.Post))
{
//thead and tbody
}
Since no answer was reported for testing the for loop instead of foreach.
I was stuck all day yesterday using foreach loop and always got 0 items in the post method. I changed to for loop and was able to receive the updated items in the post method.
For reference I am using asp.net core 3.2
This is the foreach loop:
#{
foreach(var role in #Model.RolesList)
{
<div class="btn-check m-1">
<input type="hidden" asp-for="#role.RoleId" />
<input type="hidden" asp-for="#role.RoleName" />
<input asp-for="#role.IsSelected" class="form-check-input" />
<label class="form-check-label" asp-for="#role.IsSelected">#role.RoleName</label>
</div>
}
}
This is the for loop:
#for(int i = 0;i< Model.`enter code here`RolesList.Count();i++)
{
<div class="btn-check m-1">
<input type="hidden" asp-for="RolesList[i].RoleId" />
<input type="hidden" asp-for="RolesList[i].RoleName" />
<input asp-for="RolesList[i].IsSelected" class="form-check-input" />
<label class="form-check-label" asp-for="RolesList[i].IsSelected">#Model.RolesList[i].RoleName</label>
</div>
}

How do I build up an html string to display within a div using razor mvc?

I'm using razor mvc and I want to build up an html string so that I can display it within a div, in php it would look like this:
$htmlstring = '';
foreach ($item as $items)
{
$htmlstring .= '<p>'.$item.'</p>';
}
<div>
<? echo $htmlstring; ?>
</div>
How would I do the equivalent in razor mvc?
You could just stick your code within a foreach loop on the Razor View
<div>
#foreach ( var item in Model.Items ){
<p>#item</p>
}
</div>
Assuming that the Model you pass in has a property called Items which is a Collection of some type.
I think you mean the ASP .NET MVC Razor View Engine.
#{
//this should come from controller
List<string> items = new List<string>() { "one", "two", "three" };
}
<div id="theDiv">
#foreach (var v in items)
{
//no need for building a string, sense we can just output the <p>xyz</p> inside the div
<p>#v</p>
}
</div>

How to pass the text/Value of an Html element from view to controller

I want to access the value of button in controller and then pass it to the view as well.
But the value of "str" passed from view to controller is null.
Index.chtml
#{
var str = "Shoes";
}
<a href="~/Home/Products_By_Category/#str" target="_parent">
<input type="button" value="Shoes" class="btn"/>
</a>
/////////////////////////
<pre lang="c#">
public ActionResult Products_By_Category(string s)
{
ViewBag.category = s;
return View();
}
Have the same name s for your input also.
Use ViewBag.category in the client side. Since ViewBag is a dynamic entity.
Are you using form submit in which case MVC will automatically fill the value of the input for you.
Now I'm using
Index.cshtml
#{
var str="Shoes";
}
<form action="~/Home/Products_By_Category/#str" method="post">
<input type="submit" value="Shoes" class="btn"/>
</form>
/////////////
public ActionResult Products_By_Category(string s)
{
var context = new Shoe_StoreDBEntities();
var q = from p in context.Products
join c in context.Categories on p.CategoryId equals c.Id
where c.Name.Equals(s)
select new { p, c };
}
but still the value in "s" is still null
First. The controller passes data to the view. There is no other way around. It's because the basic nature of a webapplication.
Basically: Request -> controller -> select and render a view.
The view itself is not a known concept in the client browser. That is simple html/css/js.
Your view should looks like this:
#{
var str = "Shoes";
}
#using (Html.BeginForm("Products_By_Category"))
{
<input type="submit" name="s" id="s" value="#(str)"/>
}
Some note:
1) If you use a variable inside an html element attribute you have to bracket it.
2) You should use the builtin html helper whenever it's possible (beginform)
3) This example only work if you click the submit button to postback the data. If there is other submit button or initiate the postback from js, the button data is not included into the formdata. You should use a hidden field to store the str value and not dependent from the label of the button:
#{
var str = "Shoes";
}
#using (Html.BeginForm("Products_By_Category"))
{
<input type="hidden" id="s" name="s" value="#(str)"/>
<input type="submit" value="Do postback"/>
}

How can I make sure that the newest items added to the list variable gets placed in the top and not in the bottom when it get displayed in html?

I am using MVC + EF
I have a Feed xml file url that gets updated every 7 minute with items, every time a new item gets added I retrieve all the items to a list variable and then I add these varible to my database table. After that I fill a new list variable which is my ViewModel from the database table. Then I declare the ViewModel inside my view which is a .cshtml file and loop throught all of the objects and display them.
How can I make sure that the newest items get placed on the top and not in the bottom?
This is how I display the items inside my cshtml note that I use a ++number so the newest item needs to be 1 and so on.. :
#model Project.Viewmodel.ItemViewModel
#{
int number = 0;
}
}
<div id="news-container">
#foreach (var item in Model.NewsList)
{
<div class="grid">
<div class="number">
<p class="number-data">#(++number)</p>
</div>
<p class="news-title">#(item.Title)</p>
<div class="item-content">
<div class="imgholder">
<img src="#item.Imageurl" />
<p class="news-description">#(item.Description) <br />#(item.PubDate) | Source</p>
</div>
</div>
</div>
}
</div>
This is how I fill the viewmodel which I use inside the .cshtml file to iterate throught and display the items
private void FillProductToModel(ItemViewModel model, News news)
{
var productViewModel = new NewsViewModel
{
Description = news.Description,
NewsId = news.Id,
Title = news.Title,
link = news.Link,
Imageurl = news.Image,
PubDate = news.Date,
};
model.NewsList.Add(productViewModel);
}
Sorry for the paint lol :P
Any kind of help is appreciated
#foreach (var item in Model.NewsList.OrderByDescending(n => n.PubDate)

Can I use IEnumerable<> inside a View?

In _Layout.cshtml
#model DynaPortalMVC.Models.Page
#using System.Linq
<ul>
#IEnumerable<model.Page> pages = model.Where(x=>x.CompanyID == 1);
#foreach (var item in pages)
{
<li>item.Title</li>
}
</ul>
In view iam trying to filter the model object called 'page' and get a list of pages whose id is 1. I need to iterate through this to show the menu.
Code inside Controller
public ActionResult Menu(string PageName)
{
//
return View(PageName, db.Pages);
}
Please tell me, how to filter out this model object to a list? I get errors on using IEnumerable.
Solved
I changed the model object to IEnumerable in view page.
#model IEnumerable<DynaPortalMVC.Models.Page>
You can skip assigning the result of your query into an IEnumerable variable unless you will use it somewhere else on the page. So you can just do this:
#model DynaPortalMVC.Models.Page
#using System.Linq
<ul>
#foreach (var item in model.Where(x=>x.CompanyID == 1))
{
<li>#item.Title</li>
}
</ul>
You need
# {IEnumerable<model.Page> pages = Model.Where(x=>x.CompanyID == 1);}
#model IEnumerable<DynaPortalMVC.Models.Page>
#{
ViewBag.Title = "Page";
}

Categories

Resources