Html.RenderPartial giving me strange overload error? - asp.net-mvc

I made a test partial page named _Test.cshtml and put it in the same directory as my view that will be calling it, here it is:
<div>hi</div>
And in the calling cshtml view, I simply put:
#Html.RenderPartial("_Test")
Which gives me the error:
CS1502: The best overloaded method
match for
'System.Web.WebPages.WebPageExecutingBase.Write(System.Web.WebPages.HelperResult)'
has some invalid arguments
I have also tried the full path with the same result.
I am very confused as to why this is acting this way, I assume I am missing something simple?

You are getting this error because Html.RenderXXX helpers return void - they have nothing to return because they are writing stuff directly* to response. You should use them like this:
#{ Html.RenderPartial("_Test"); }
There is also Html.Partial helper, which will work with your syntax, but I'd not recommend using it unless you have to, because of performance (it first composes given partial view into string, and then parent view puts it into response*).
* this is not entirely true, they are actually being rendered into ViewContext.Writer and once whole page is rendered and composed, the whole thing goes to response

Related

A public action method '..' was not found on controller '..'

I wanted to put a random image on every viewpage of my mvc project. So i created a method that returns a partialView and call that method in the shared Layout page.
This works fine when I try to login with a correct username and password. The used is loged in and every page contains a random image. But when I give the invalid combination of username and password. The shared layout page does not find the controller I want to call with my #Html.Action and actualy the login view should be returned with an error message 'invalid combination of username and password' and ofcourse, with the random image.
InnerException:
{"A public action method 'RandomSponsor' was not found on controller 'Project.WebUI.Controllers.HomeController'."}
My Html.Action in shared layout.
#Html.Action("RandomSponsor", "Home")
Method in homecontroller.
[HttpGet]
[ChildActionOnly]
public ActionResult RandomSponsor()
{
var model = service.getRandomSponsor();
return PartialView("RandomSponsor", model);
}
The getRandomSponsor method works fine, this one always returns one random string value that is returned to the RandomSponsor.cshtml view.
RandomSponsor.schtml (only contains the image string)
<img src="~/Content/Images/Advert/#(Model)" alt="a" />
I searched the web for this problem but didn't found a solution, does anyone know the answer to this one?
Might it be something with HttpGet of HttpPost?
Regards.
If the executing request is a POST, then it will try to find a method RandomSponsor accepting HttpPost. If this makes sense, you could remove HttpGet and that should do the trick.
This can also happen if you have many layers of calls that start with a POST (I had an action returning a view returning a partial view calling RenderAction), then the call to RenderAction will still look for a POST method
Very similar to this problem that I had here - How to solve "public action method 'methodActionName' was not found on controller 'controllerNameController'"
And if you want to continue to accept the HTTP GET verb and fix the problem of cascading post request into a get request add this to your method
[AcceptVerbs(HttpVerbs.Get | HttpVerbs.Post)]
Keep in mind that [HttpGet] is the same as [AcceptVerbs(HttpVerbs.Get)]
This will happen if the request is a POST but the controller method is annotated [HttpGet]. For example, you might issue a POST that returns a view containing partial views called with #Html.Action, using controller methods annotated with [HttpGet]. If the original request is a POST, all of the controller methods subsequently called will need to support POST.
To fix it you can use the AcceptVerbs attribute to specify that your controller method accepts both POST and GET:
[AcceptVerbs(HttpVerbs.Post | HttpVerbs.Get)]
Received this error all of the sudden on several different PartialViews (not all of them) when customizing an install of MVCForum. We had not made any changes to the methods or views concerning the errors so it was really frustrating as to why they were broken.
After trying the other solutions on this post and others, went back through the changes made and what ended up stopping the errors was that we had changed the bindings in IIS to another domain that had the 'enforce lower case url' URL Rewrite rule enabled.
When we disabled the enforce lowercase rule, the errors stopped and the site worked as it was supposed to. It's not a URL Rewrite issue (I don't think) because we are able to enforce www using it with no errors. It's a lowercase rewrite issue. Didn't matter if we had the lowercase rule before or after the www rule.
This solution probably doesn't apply to many cases of this error, but it worked for us. Hopefully someone else can benefit from such a simple fix.
I just solved this issue strangely enough on my local PC, by making sure my entire request path was lower case. So give that a try.
I know this is a pretty old thread - but as it's top Google result I thought I'd add a potentially missing link for MVC.Net 5.2.6.
Scenario
I was attempting to call a child action via #Html.Action("ActionName", new { Id = 123})
and received an error much like the above, but none of the other solutions worked. I could hit the controller action externally (i.e. HttpGet), but the child action kept throwing the exception and was driving me nuts!
The solution I found
After two-ing and fro-ing for some time, I started playing with my routing attributes. I had the controller set up as:
[Route("{action}")]
[RoutePrefix("Prefix")]
[RouteArea("AreaName")]
As there was only one public action i wanted, "Index", I removed the {action} and placed an explicit route attribute on the public action and put my ChildActionOnly attribute back on the child.
After I did that, I hit the run and hey presto - the action was hit.
Might be worth a try if you're getting this error while using attribute routing. Note I did attempt to route the child action and this didn't work.
In my case, the same issue was happening randomly with the implicit :
using (Html.BeginForm())
Changing above to :
using (Html.BeginForm("Action","Controller", FormMethod.Post))
fixed this issue.
Did you give it a shot with Html.RenderAction? It is typically faster then Html.Action as it interact directly into the response stream as opposed to building a string.
You can view the following topics for more info:
What is the difference (if any) between Html.Partial(view, model) and Html.RenderPartial(view,model) in MVC2?
Html.Partial vs Html.RenderPartial & Html.Action vs Html.RenderAction
Another thing to note is that for Html.Action or Html.RenderAction, your view doesn't need to be in Shared folder, that is only required if you use Html.Partial or Html.RenderPartial

Should I create HtmlHelper extension method to reduce duplication of rendering partial views?

Let's say I have a Statistic view that will display on different pages.
Without any helpers, I have to using following code:
#section Statistic{
#Html.RenderAction("Index", "Statistic", new { id = Model.UserId });
}
But with creating a helper, I can write something like:
#section Statistic{
#Html.Stats().For(Model.UserId);
}
Then any future changes in Controller, ActionName or parameter of the Statistic controller will need to be changed in 1 place which is in my StatsHtmlHelper
Some of my colleagues complain that this helper does nothing but call the RenderAction then it should not exist. What is your opinion?
With creating helper method, you reduce the complexity of calling RenderAction, ActionLink and such methods, and get rid of the "magic strings". But for every different action, you have to create another helper with your approach(!), and this may be creating other complexity, especially when there already exist community tools for making life simpler in cases like that. If you do that for statistics, why wouldn't you do that for every other action in your application? I would use T4MVC with its RenderAction, ActionLink overloads that accept ActionResult. With it, you get rid of magic strings and get compile time exceptions when your controller, action or parameter signature changes. With exact places marked with error by compiler, fixing them is easier. With T4MVC, your statistics rendering line would be:
#{Html.RenderAction(MVC.Index.Statistic(Model.UserId));}
And T4MVC methods are for general approach. You can simply use them for every single action throughout your project

Razor: #Html.Partial() vs #RenderPage()

What is the appropriate way of rendering a child template?
And what's the difference? Both seem to work for me.
And why does #Html.RenderPartial() no longer work?
Html.Partial("MyView")
Renders the "MyView" view to an MvcHtmlString. It follows the standard rules for view lookup (i.e. check current directory, then check the Shared directory).
Html.RenderPartial("MyView")
Does the same as Html.Partial(), except that it writes its output directly to the response stream. This is more efficient, because the view content is not buffered in memory. However, because the method does not return any output, #Html.RenderPartial("MyView") won't work. You have to wrap the call in a code block instead: #{Html.RenderPartial("MyView");}.
RenderPage("MyView.cshtml")
Renders the specified view (identified by path and file name rather than by view name) directly to the response stream, like Html.RenderPartial(). You can supply any model you like to the view by including it as a second parameter
RenderPage("MyView.cshtml", MyModel)
I prefer
#RenderPage("_LayoutHeader.cshtml")
Over
#{ Html.RenderPartial("_LayoutHeader"); }
Only because the syntax is easier and it is more readable. Other than that there doesn't seem to be any differences functionality wise.
EDIT: One advantage of RenderPartial is you don't have to specify the entire path or file extension it will search the common places automatically.
The RenderPartial method doesn’t return HTML markup like most other helper methods. Instead, it writes
content directly to the response stream, which is why we must call it like a complete line of C#, using a semicolon.
This is slightly more efficient than buffering the rendered HTML from the partial view, since it will be written to the
response stream anyway. If you prefer a more consistent syntax, you can use the Html.Partial method, which
does exactly the same as the RenderPartial method, but returns an HTML fragment and can be used as
#Html.Partial("Product", p).
We can also pass model using partial views. #Html.Partial("MyView","MyModel");
#RenderPages()
The above does not work in ASP.NET MVC. It only works in WebPages.
#Html.Partial("_Footer")
You will need to use the above in ASP.NET MVC.
For ASP.NET Core 7. In the Shared folder make partial file then user this following code
<partial name="_NavBar" />

The model item passed into the dictionary is of type

I have an error that I kind of understand, but can't figure out to solve in the right way.
I have a MasterPage, from that MasterPage I call:
<% Html.RenderPartial("Tags"); %>
Tags is a strongly typed view that looks like this:
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<IEnumerable<JegManglerEn.Controllers.CategoryCount>>" %>
I return the PartialView like this:
return View("Tags", result);
where result is correct and of type:
List<CategoryCount>
The error is this:
The model item passed into the dictionary is of type 'System.Collections.Generic.List1[JegManglerEn.Item]', but this dictionary requires a model item of type 'System.Collections.Generic.IEnumerable1[JegManglerEn.Controllers.CategoryCount]'.
So the setup is this:
MasterPage loads a View that takes a collection of JegManglerEn.Item AND also tries to load a PartialView that takes a collection of a JegManglerEn.Controllers.CategoryCount...but fails to do so.
I know it has something to do with the RenderPartial method because if I change it to RenderAction it's works great.
If you guys have the answer I get to skip looking at the MVC soruce or startup Reflector.
Thanks!
When you call the single-parameter overload of Html.RenderPartial, you're implicitly passing the entire model of the parent view down to the partial. This doesn't work, as the model types expected by the views do not match.
The simplest way to get RenderPartial working in your context is to create a composite model type that contains both the Tags and the page model data, then call the overload where you pass a part of the parent model to the partial:
Html.RenderPartial("Tags", Model.Tags);
That being said, I think RenderAction is most likely the way to go here, as it makes it easier to avoid duplicate code in your controllers (of course assuming you're loading the tags data in the same way for all pages inheriting from the masterpage in question).
Change the
ViewUserControl<IEnumerable<JegManglerEn.Controllers.CategoryCount>>
to
ViewUserControl<List<JegManglerEn.Controllers.CategoryCount>>

ASP.NET MVC: Custom Html Helpers in Razor

I am having difficulty with Html Helpers when used with Razor. Said helpers worked fine in MVC 2 with the web form view engine. But not in razor. The error I get at runtime is:
Compiler Error Message: CS1502: The best overloaded method match for 'System.Web.WebPages.WebPageExecutingBase.Write(System.Web.WebPages.HelperResult)' has some invalid arguments
Source Error:
Line 1: #using Wingspan.Web.Mvc;
Line 2: #Html.IncrementalMenu(MenuBlock.Site)
Expanding the Show Detailed Compiler Output reveals:
d:\...\Views\Shared\MenuTop.cshtml(2,1): error CS1502: The best overloaded method match for 'System.Web.WebPages.WebPageExecutingBase.Write(System.Web.WebPages.HelperResult)' has some invalid arguments
d:\...\Views\Shared\MenuTop.cshtml(2,7): error CS1503: Argument 1: cannot convert from 'void' to 'System.Web.WebPages.HelperResult'
That indicates to me that razor doesn't like my helper, IncrementalMenu, returning void (which works fine in MVC 2 web form engine views).
I get no errors at Compile time, although the line of code (#Html.IncrementalMenu(...)) is red underlined with the following message:
Cannot implicitly convert type 'void' to 'object'
IncrementalMenu is in the Wingspan.Web.Mvc namespace. It's signature is as follows:
public static void IncrementalMenu(this HtmlHelper html, MenuBlock menuBlock)
{
// Uses an HtmlTextWriter to render a menu from the sitemap
}
I'm blowed if I know what is wrong...
PS:
The MenuBlock parameter is just an enum that identifies how the menu should render. Don't fixate on this as that is fine.
You can call your helper like this:
#{ Html.IncrementalMenu(MenuBlock.Site); }
WebForms syntax
<% Html.IncrementalMenu(MenuBlock.Site); %>
You just call your method, and the return value (if there is any) is ignored.
Code like this expects a return value, and writes the return value to the html stream:
#Html.YourHelper()
Webforms syntax:
<%: Html.YourHelper() %>
The same, if result value != IHtmlString:
<%= Server.HtmlEncode(Html.YourHelper()) %>
Addendum:
You can get the same, or similar, error with #Html.RenderPartial. In this case it is due to the fact that RenderPartial renders directly to the Response, so is not a string and needs to be coded inside a "Razor code block":
#{
Html.RenderPartial(...);
}
I suspect that is one of the reasons that Microsoft have included in ASP.NET MVC the new Html.Partial. As Html.Partial does return a string, it is OK to write:
#Html.Partial
Which looks a lot better. Given that one of Razor's declared objectives is to be easy on the eye, this is quite likely true.
It also kind of makes me, at least, feel more comfortable. I know what returning a string is, I do it all the time. But "returning to the Response" requires a few more brain cycles every time I think it.
And it fits with the old adage that finally Microsoft get their products right in version 3. EG, Access 97.
Which is a depressing simile. Cos they screwed things up in version 4, ie, Access 2000...
Your HTML helper should return MvcHtmlString which represents the html in order to work properly with Razor (and other view engines that are not the WebFormsViewEngine)
public static MvcHtmlString Label(this HtmlHelper html, string expression)
{
return MvcHtmlString.Create("<label>" + expression + "</label>");
}

Resources