RenderPartialForEach<T>(..) HtmlHelper for asp.net mvc? - asp.net-mvc

This throws error:
public static void RenderPartialForEach<T>
(this HtmlHelper helper, string partialName, IList<T> list)
{
foreach (var item in list)
helper.RenderPartial(partialName, item);
}
=>
Error Message: CS1519: Invalid token '(' in class, struct, or interface member declaration
Line 283: #line default
Line 284: #line hidden
Line 285: #__w.Write("\r\n \r\n\r\n\r\n");
Line 286: }
Line 287:
Is it possible to create clean htmlhelper
which is able to render partial views for every item in list passing it as model?
Edit:
That was just a blunder from my side. I forgot to add '<% } %>'.
And got confused cause of error message. ^^

You need to declare the method in a class. It's not obvious that you are doing that, but it would certainly cause the type of error that you are seeing.
public static class CustomHtmlHelperExtensions
{
public static void RenderPartialForEach<T>(
this HtmlHelper helper,
...
}
EDIT: In retrospect, given the text of the error, I suspect that the error lies elsewhere in your markup. Perhaps, you're missing a parenthesis around an if statement or foreach clause.

Where are you declaring such a thing? Try writing that extension method in a separate static class in a code file, not inline in .aspx.

Just a guess... you are implementing a generic method (of T) but you are not actually replacing the generic parameter (T) with a type argument?

Related

HTML Helper how to use IEnumerable

I want to create a custom HTML Helper where I can pass a LINQ expression as a parameter, like this:
#Html.GetBackgroundColor(model => model.RiskAssessment)
I want to use it to display some custom css in an MVC view, depending on what the RiskAssessment property is.
So I created a helper method like this:
public static string GetBackgroundColor<T, TResult>(this HtmlHelper<T> htmlHelper, Expression<Func<T, TResult>> expression)
{
...
}
However, that won't compile, the error is IEnumerable does not contain a definition for 'RiskAssessment'
So I changed the method to
public static string GetBackgroundColor<T, TResult>(this HtmlHelper<IEnumerable<T>> htmlHelper, Expression<Func<T, TResult>> expression)
{
...
}
which compiles, so now I presumably have all the objects in the collection but I have no idea how to get the object I want as I can't use use the expression on the IEnumerable, there is no Where() method available. I would have thought I could do something like this:
IEnumerable<T> collection = htmlHelper.ViewData.Model;
T obj = collection.Where(expression)
but I just don't know what I am doing wrong here.
Figured it out, simple mistake. The table header row is set up with #Html.DisplayNameFor(model => modelType), and I was trying to call my custom HTML helper with these parameters. I should have been calling the method on each table row, using #Html.GetBackgroundColor(modelItem => item.RiskAssessment), and this works because I can use htmlHelper.ValueFor(expression) within the method to get the property value.
That said, I have no idea how the header row is generated as Html.DisplayNameFor uses the same method signature as my custom method but Intellisense reports that one of the Expression types is unknown. But that is not an issue for me.
Thanks.

Asp.Net HtmlHelper with a Generic only work inside a #Razor statement

I would like to understand why the following code does not work while the second work:
#Html.Test<ContestListItemViewModel>() //Does not work
#{
var x = Html.Test<ContestListItemViewModel>();//Work
#Html.Raw(x);//Work
}
The code of this Test helper is very simple:
public static MvcHtmlString Test<TEntityType>(this HtmlHelper htmlHelper)
{
return new MvcHtmlString("<p>Test</P>");
}
The error is during the execution:
An exception of type 'System.Web.HttpCompileException' occurred in
System.Web.dll but was not handled in user code
Compiler Error Message: CS1502: The best overloaded method match for
'System.Web.WebPages.WebPageExecutingBase.Write(System.Web.WebPages.HelperResult)'
has some invalid arguments
The Razor parser is confused. It doesn't know if that is HTML or C#.
Try:
#(Html.Test<ContestListItemViewModel>())
In the second example the statement is wrapped in a Razor code block, so it knows for sure.
Wrapping in parentheses can often solve code confusion problems like this.

TModel not recognized in a Razor Helper as Lamba Expression

I trying to use a Razor Helper that does some if statements for me. I'm passing it a list with certain rules and based on that rule a label and input text field are created.
The problem I have is I can't get it to work with a Lambda expression as parameter. It won't recognize the TModel part.
The helper method is as follows:
#helper CreateCheckbox(Expression<Func<TModel, bool>> expression, object htmlAttributes, List<Rule> ruleList)
{
}
The error I get is: The type of namespace 'TModel' can not be found.
You have to pick a type for TModel. Because your view doesn't have any generic type parameters, there is no way for it to figure out what type it should substitute in for TModel. You have to give it an actual type to work with.
If that's not an option, you might just make an extension method for the HtmlHelper class, and make it a generic method. See this question for an example of how to do that.

ASP.NET MVC Razor - lambda error

I have an extension method
public static HelperResult List<T> (this IEnumerable<T> items, Func<T, HelperResult> template) {
return new HelperResult(writer =>{
foreach (var item in items)
template(item).WriteTo(writer);
});
}
When I try to use this method like this
<ol>
#Model.List(t=> {#<li>#t.Title</li>});
</ol>
I get an error "; expected"
But if I do
<ol>
#Model.List( #<li>#item.Title</li>)
</ol>
it's OK. (what is the variable "item"? Where does it define?)
Why does the first example throws an error?
The one solution is to declare razor helper like this
#helper ItemWriter(string item)
{
<li>#item.Title</li>
}
And then pass this to your extension function
#Model.List(ItemWriter)
I know this code can be made better, but this works. Main idea is to use Razor Helpers
The syntax #<tagname>...</tagname> declares a lambda expression that takes a parameter named item and returns a HelperResult.
You cannot use it as a statement; your first example cannot work.
That's pretty much the reason why I had to create Castle.Blade. It supports #=> p ... as an expression to create a lambda with named args. It also supports nesting these declarations, which razor doesn't.

Render partial view with dynamic model in Razor view engine and ASP.NET MVC 3

When I try to render a partial view whose model type is specified as:
#model dynamic
by using the following code:
#{Html.RenderPartial("PartialView", Model.UserProfile);}
I get the following exception:
'System.Web.Mvc.HtmlHelper<dynamic>' has no applicable method named 'RenderPartial' but appears to have an extension method by that name. Extension methods cannot be dynamically dispatched. Consider casting the dynamic arguments or calling the extension method without the extension method syntax.
However, the same code in a .aspx file works flawlessly. Any thoughts?
Just found the answer, it appears that the view where I was placing the RenderPartial code had a dynamic model, and thus, MVC couldn't choose the correct method to use. Casting the model in the RenderPartial call to the correct type fixed the issue.
source: Using Html.RenderPartial() in ascx files
Instead of casting the model in the RenderPartial call, and since you're using razor, you can modify the first line in your view from
#model dynamic
to
#model YourNamespace.YourModelType
This has the advantage of working on every #Html.Partial call you have in the view, and also gives you intellisense for the properties.
Can also be called as
#Html.Partial("_PartialView", (ModelClass)View.Data)
There's another reason that this can be thrown, even if you're not using dynamic/ExpandoObject. If you are doing a loop, like this:
#foreach (var folder in ViewBag.RootFolder.ChildFolders.ToList())
{
#Html.Partial("ContentFolderTreeViewItems", folder)
}
In that case, the "var" instead of the type declaration will throw the same error, despite the fact that RootFolder is of type "Folder. By changing the var to the actual type, the problem goes away.
#foreach (ContentFolder folder in ViewBag.RootFolder.ChildFolders.ToList())
{
#Html.Partial("ContentFolderTreeViewItems", folder)
}
Here's a way to pass a dynamic object to a view (or partial view)
Add the following class anywhere in your solution (use System namespace, so its ready to use without having to add any references) -
namespace System
{
public static class ExpandoHelper
{
public static ExpandoObject ToExpando(this object anonymousObject)
{
IDictionary<string, object> anonymousDictionary = HtmlHelper.AnonymousObjectToHtmlAttributes(anonymousObject);
IDictionary<string, object> expando = new ExpandoObject();
foreach (var item in anonymousDictionary)
expando.Add(item);
return (ExpandoObject)expando;
}
}
}
When you send the model to the view, convert it to Expando :
return View(new {x=4, y=6}.ToExpando());
Cheers
I had the same problem & in my case this is what I did
#Html.Partial("~/Views/Cabinets/_List.cshtml", (List<Shop>)ViewBag.cabinets)
and in Partial view
#foreach (Shop cabinet in Model)
{
//...
}
I was playing around with C# code an I accidentally found the solution to your problem haha
This is the code for the Principal view:
`#model dynamic
#Html.Partial("_Partial", Model as IDictionary<string, object>)`
Then in the Partial view:
`#model dynamic
#if (Model != null) {
foreach (var item in Model)
{
<div>#item.text</div>
}
}`
It worked for me, I hope this will help you too!!

Resources