How to check ViewBag contains a specific string - c#

In controller I have:
string[] checkedBoxes
ViewBag.Funds = checkedBoxes;
checkedBoxes is posted by a form in the view page. How do I check inside the view if ViewBag.Funds contains a specific string?
I tried:
#if (ViewBag.Funds.ContainsKey("a"))
{
}
I got this error: RuntimeBinderException: 'System.Array' does not contain a definition for 'ContainsKey'
.Contains() also doesn't work even though I used #using System.Linq

You have to cast the ViewBag property to the type first. Try this
#if (((string[])ViewBag.Funds).Contains("a"))
{
}

#if (ViewBag.Funds.Any(s=>s.Contains("a"))))
{
}

Related

Html extension method not working in form

I have the following form:
#using (Html.BeginForm("Cancel", "Member", FormMethod.Post))
{
Html.SubmitButton(); //doesn't work
}
#*#Html.SubmitButton(); //does work*#
The extension method looks like this:
public static MvcHtmlString SubmitButton(this HtmlHelper helper)
{
return new MvcHtmlString("<input type = \"submit\" value = \"Cancel\" />");
}
Why is the input element HTML able to be generated outside the using block but not inside it?
You missing the leading # which tells razor to output the results to the view. When you use just Html.SubmitButton();, the method is executed and the result is returned, but nothing is done with it.
Your code needs to be
#using (Html.BeginForm("Cancel", "Member", FormMethod.Post))
{
#Html.SubmitButton()
}

How to create server method, that populates collection and returns partial view, in ASP.NET MVC?

I am trying to call IEnumerable method in my _Layout.cshtml file. At the final I was adviced to "use html.action - to call server method that populates collection and returns partial view".
Currently I have created partial file _Dodatki.cshtml, that contains call of IEnumerable method (Aktualnosci.cs is model file):
#model IEnumerable<DluzynaSzkola.Models.Aktualnosci>
In my _Layout.cshtml I called method from my constructor with:
#Html.Action("_Dodatki", "AktualnosciController ", new {area="" })
And at the final I want to create method in my AktualnosciConstructor.cs file. Currenly I have method:
[ChildActionOnly]
[ActionName("_Dodatki")]
public ActionResult Dodatki()
{
IList<Aktualnosci> lista = new IList<Aktualnosci>();
return PartialView("_Dodatki", lista);
}
Unfortunately, when using syntax as above, it gives me message in compiler:
"cannot create an instance of the abstract class or interface
'IList'".
When replacing 'IList' with 'List', it gives me exception:
"System.Web.HttpException: The controller for path '/' was not found
or does not implement IController."
I have no idea how in other way I can populate collection in the method.
edit: As per request, below AktualnosciController.cs definition, with no other methods:
namespace DluzynaSzkola.Controllers
{
public class AktualnosciController : Controller
{
//here are other methods
[ChildActionOnly]
[ActionName("_Dodatki")]
public ActionResult Dodatki()
{
IList<Aktualnosci> lista = new IList<Aktualnosci>();
return PartialView("_Dodatki", lista);
}
}
}
as noticed by GTown-Coder your controller name seems wrong. Updated my answer accordingly.
I think that your problem might be the same as answered by this SO post.
try specifying the Area name and, if this controller is not in an area simply add an empty area name.
#Html.Action("_Dodatki", "AktualnosciController ", new {area="" })
Even if this does not solve your problem it is good practice because if this view is latter used within an area it will try to find the controller in the area and not in the root space.
Allright, I have implemented changes to my project, that works fine.
My in _Layout.cshtml call is changed a bit. AktualnosciController supposed to be called just Aktualnosci !!!
<div class="kontenerDodatkiLayout hidden-xs hidden-sm">
<div class="archiwum">Archiwum</div>
#Html.Action("_Dodatki", "Aktualnosci", new { area = "" })
</div>
My partial view _Dodatki.cshtml model call is changed a bit:
#model IEnumerable<DateTime>
<div class="wpisDodatki">
#foreach (var item in Model)
{
<div> #Html.DisplayFor(modelItem => item)</div>
}
<p>test<br />test<br />test</p>
</div>
And method in my controller AktualnosciController.cs looks like that:
//[ChildActionOnly]
[ActionName("_Dodatki")]
public ActionResult Dodatki()
{
using (var context = new DluzynaContext())
{
var lista = context.Indeks.Select(it => it.Dzien).ToList();
return PartialView("_Dodatki", lista);
}
}
in here lista is passed to my partial view _Dodatki, and it is populated with context property Indeks and model property Dzien.
Thanks guys for your help #Wndrr , #GTown-Coder.

Set TextBox value from ViewBag list in MVC5 C#

How can I set TextBox value in MVC5 from ViewBag which contains a list? As you can see my list is in Viewbag.photos and I want to have each value of photo.id in my TextBox and then pass it to controller
#foreach (var photo in ViewBag.photos)
{
#if (#photo.comment != null)
{
<h6>#photo.comment</h6>
}
else
{
<h6> - </h6>
}
#Html.TextBox("photoID", #photo.id)
}
Trying to do that I get an error:
Error CS1973 'HtmlHelper>' has no applicable method
named 'TextBox' but appears to have an extension method by that name.
Extension methods cannot be dinamically dispached.
Maybe there's another workaround?
This is happening because ViewBag.photos is a dynamic object. The compiler cannot know its type, so you have to manually cast it to its original type.
For example:
#Html.TextBox("photoID", (int)photo.id)
As a side note (I'm not sure whether this will prevent your code from working, but it's good practice anyway), you also have bit too many #s: to cite Visual Studio, once inside code, you do not need to prefix constructs like "if" with "#". So your final code will look like:
#foreach (var photo in ViewBag.photos)
{
if (photo.comment != null)
{
<h6>#photo.comment</h6>
}
else
{
<h6> - </h6>
}
#Html.TextBox("photoID", (int)photo.id)
}
You should also consider using ViewModels instead of ViewBag to pass data between your controllers and your views.

How to render derived types of a class differently?

I have an Item class. I have around 10-20 derivatives of it each containing different types of data. Now when it comes to rendering different types of Item, I'm forced to use likes of:
<div>
#if (Model is XItem)
{
... rendering logic 1 ...
}
#if (Model is YItem)
{
... rendering logic 2 ...
}
#if (Model is ZItem)
{
... rendering logic 3 ...
}
... goes on and on forever ...
</div>
Unfortunately #Html.DisplayFor() does not work in this case because the Model is type of Item, DisplayTemplates\Item.cshtml is displayed.
HTML helpers don't help either because of the same "if/is" chain.
I could incorporate rendering logic inside the classes themselves, and call #Model.Render() but they belong to business logic, not presentation. It would be a sin.
There is only one option of #Html.Partial(Model.GetType().Name) but it feels wrong. You expect a solution without meta-magic. Is there a better way?
Use Display Templates.
Inside your ~/Views/Shared/DisplayTemplates folder you can add a view with the same name as your type.
When you do #Html.DisplayFor(item) you'll get the view related to that specific type.
UPDATE
I just saw your comment RE DisplayFor so if this doesn't help i'll remove my answer.
I think your approach is fine. You can make it better with an extension method like this:
public static MvcHtmlString GetTypePartial<T>(this HtmlHelper htmlHelper, T model, string viewPrefix = "")
{
string typeName = typeof (T).Name;
string viewName = string.Concat(viewPrefix, typeName);
return htmlHelper.Partial(viewName, model);
}

Why is Orchard auto-encoding strings to the view?

In my driver, I am passing the dynamic object to the view, but it is automatically encoding all my strings which is mangling the links I am constructing in the view.
Here is what I am trying to do:
public class SomeWidgetDriver : ContentPartDriver<SomeWidgetPart>
{
// GET
protected override DriverResult Display(SomeWidgetPart part, string displayType, dynamic shapeHelper)
{
return ContentShape("Parts_SomeWidget",
() => shapeHelper.Parts_SomeWidget(
AppUrl: part.AppUrl,
AppVersion: part.AppVersion,
RenderTo: part.RenderTo,
Test: "xxxx&"));
}
}
When I add the below to the view:
#Model.Test
It renders like this:
xxxx&
Is there a way to stop this from happening? I am trying to get it to exactly render "xxxx&".
I don't think this has to do with Orchard at all.
In Razor everything is html encoded.
Did you try:
#Html.Raw(Model.Test)
?

Categories