Html extension method not working in form - c#

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()
}

Related

How to check ViewBag contains a specific string

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"))))
{
}

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.

EditorTemplate inheritance - is there a way

EditorTemplates are great since they allow some kind of "polymorphism" in razor views. But I am missing one "brick" to complete the polymorphism support:
Can an EditorTemplate for a special type inherit from the EditorTemplate for the general type?
Long version:
Given
class SpecialChild : GeneralChild { }
class Parent
{
GeneralChild AGeneralChild { get; set; }
SpecialChild ASpecialChild { get; set; }
}
and two editor templates
#* GeneralChild.cshtml *#
#model GeneralChild
<span>GeneralChild</span>
#* SpecialChild.cshtml *#
#model SpecialChild
<span>SpecialChild is a</span> <span>GeneralChild</span>
What I get (which is why I call it "polymorphism") is:
#* Index.cshtml *#
#Html.EditorFor(m => m.AGeneralChild)
// prints "<span>GeneralChild</span>", however
#Html.EditorFor(m => m.ASpecialChild)
// prints "<span>SpecialChild is a</span> <span>GeneralChild</span>"
That is, even though SpecialChild is a GeneralChild and there is a template for GeneralChild, it auto-selects the SpecialChild.cshtml template. Furthermore, if I remove that template, it falls back to the GeneralChild.cshtml template. In other words, it is possible to reuse a general template or to override it if necessary.
Now for what I would really like:
I would like to reuse the GeneralChild.cshtml template to define the SpecialChild.cshtml template, like a "base method" call in C#. In pseudo-code:
#* SpecialChild.cshtml *#
baseEditorFor()
#section SpecificPart
{
<span>SpecialChild is a </span>
}
#* GeneralChild.cshtml *#
#Html.RenderSection("SpecificPart") <span>GeneralChild</span>
Is something like that supported?
What I have tried so far:
GeneralChild.cshtml:
#model GeneralChild
#{
var extend = ViewData.ContainsKey("Extend")
? (MvcHtmlString)ViewData["Extend"]
: null;
}
#if (extend != null) { #extend }
<span>GeneralChild</span>
SpecificChild.cshtml:
#model SpecialChild
#Html.EditorFor(
m => m, // call editor for my model
"GeneralChild", // but call "base" instead of "this"
new
{
// Hand the HTML to insert as ViewData parameter
Extend = new MvcHtmlString("<span>SpecialChild is a </span>")
})
Unfortunately, #Html.EditorFor(m => m) does not do anything. That makes sense because m => m is not the same expression as the original m => m.ASpecialChild.
I thought I could build up the expression tree by hand, but then I realized that the type arguments within the editor template are (of course) different from the ones in the Index.cshtml. #Html in the original call is typed <Parent> whereas within the template it is <SpecialChild>.
Then I tried another approach which is the closest I got so far:
Within the Index.cshtml I define a razor helper:
#helper SpecialChildEditorFor(Expression<Func<Parent,SpecialChild>> expression)
{
#Html.EditorFor(
expression,
"GeneralChild",
new { Extend = new MvcHtmlString("<span>SpecialChild is a </span>") })
}
Then I call this instead of EditorFor:
#SpecialChildEditorFor(m => m.ASpecialChild)
But of course this lacks the entirety of the the initially mentioned advantages - I can't simply drop this snippet in the EditorTemplates directory, thus "overriding" the GeneralChild.cshtml template. Also, it needs to be explicitly called (so we lost "polymorphism", too). Even more, the razor helper is tied to the Index.cshtml page:
* It has to be defined within the page where it is used.
* It relies on expression to have the same type arguments as the one the page needs.
Use Partial in editor template insted of #Html.EditorFor(m => m, ...):
#model SpecialChild
#{
ViewData["Extend"] = new MvcHtmlString("<span>SpecialChild is a </span>");
}
#Html.Partial("~/Views/Shared/EditorTemplates/GeneralChild.cshtml", Model)

MVC4 - How to call controller method from razor view

i am new with MVC, can someone please help me and explain how to call controller method from a view.
I have HomeController and inside it I have method ShowFileContent().
[HttpPost]
public ActionResult ShowFileContent()
{
string filepath = Server.MapPath("\\Files\\Columns.txt");
try
{
var lines = System.IO.File.ReadAllLines(filepath);
foreach (var line in lines)
{
ViewBag.FileContent += line + "\n";
}
}
catch (Exception exc)
{
ViewBag.FileContent = "File not found";
}
return View();
}
Inside view I've tried to call this method with code bellow but it does not work.
#using (Html.BeginForm("ShowFileContent", "Home"))
{
<input type="submit" value="Show File" style='width:300px'/>
}
<h2>#Html.Raw(ViewBag.FileContent.Replace("\n", "</br>"))</h2>
I get error: The view 'ShowFileContent' or its master was not found or no view engine supports the searched locations.
What i am doing wrong and whats the best way to call methods from razor view ?
You can use inbuilt Action method to call action from View.
#Html.Action("actionName", "ControllerName")
It sounds to me like its breaking on your
return View();
If you dont tell it where to go it thinks the view is called the same as your action.
so instead try
return View("Name of your view");

Render partial in an extension method fails

I'm creating a tabcontainer that shows information from partials. The code that i've created is as follows:
//Entering extension method, m_helper is of type HtmlHelper
foreach (var tab in m_tabList)
{
sb.AppendLine("<div class='tabContent'>");
m_helper.RenderPartial(tab.PartialName);
sb.AppendLine("</div>");
}
//Returning sb.ToString to the caller method
This will not work because the renderpartial writes directly to the output stream. I cannot render the partial to a string either. to add it to the stringbuilder object.
Any suggestions?
use
m_helper.Partial(tab.PartialName);
This will return MvcHtmlString.

Categories