This is probably a quick fix, but I am writing to a HtmlTextWriter in my HtmlHelper and no matter what I try it is encoding the HTML so the output shows the markup.
Helper:
protected override void WriteHtml(System.Web.UI.HtmlTextWriter writer)
{
writer.WriteFullBeginTag("div");
writer.WriteEndTag("div");
base.WriteHtml(writer);
}
and it will out put this to the page: <div></div>
EDIT
I am calling it in the view like this:
#Html.SAIF().Toolbar().Items(items => {
items.Add().Action("Action");
... ...
})
Edit #2
OK, let's see if I can explain this a little better.
If I use ViewContext.Writer to write my helper to the stream, when using a syntax like this:
#Html.MyHelper
It outputs encoded HTML (e.g.) <div>Test Div</div> = Not correct
If I use a syntax like this:
#{Html.MyHelper.Render();}
It renders correctly, meaning that it actually inserts the div into the DOM instead of displaying it as a string.
Make sense?
Related
I'm trying to set a master layout.cshtml page that works consistently for all page except for one or two (typically login and logout). In my layout I'd like to display some elements that I want to not display for these special pages.
I've seen partial views and sections and they all seem to work "backwards" to the way I want - in this case I want the default to be 'display all the elements', but for special pages I want to be able to turn an element off.
I've seen previous code that uses PageData to pass a variable to the layout (which seemed very useful as I could slap a bool in the relevant pages and check it in the layout) but this seems to have been removed. Are there any other ways that work without involving the controller or updating every page to display the bits I want hidden on just 1 page?
There's a number of different ways you can achieve this. If you want to simply "turn off" an area of the page, the simplest approach is probably with ViewData. Something like:
_Layout.cshtml
#if (ViewData["ShowThis"] as bool? ?? true)
{
<!-- HTML here -->
}
This will cause it to default to true (show the HTML) if the ViewData key is not defined, so then in your views where you want to disable it, you'd just need to define it as false:
SomeView.cshtml
#{
ViewData["ShowThis"] = false;
}
Alternatively, you can use sections. This would give you the ability to optionally replace the HTML with something else.
_Layout.cshtml
#if (!IsSectionDefined("Foo"))
{
<!-- HTML here -->
}
else
{
#RenderSection("Foo", required: false)
}
Then, in your view, you simply define the section. If you want to display nothing, you can just define it empty:
SomeView.cshtml
#section Foo {}
Or you can can actually put something in there to replace the area with:
#section Foo
{
<!-- alternate HTML here -->
}
You can try this to pass ViewData in _Layout page in asp.net mvc
public class DynamicMenuAttribute : ActionFilterAttribute
{
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
base.OnActionExecuted(filterContext);
var result = filterContext.Result as ViewResult;
result.ViewData["key"] = "Hello Bangladesh";
}
}
Add Dependency Injection into Startup.cs file
services.AddMvc(
config =>
{
config.Filters.Add(new DynamicMenuAttribute());
}).SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
Now you can you ViewData["key"] in _Layout.cshtml
Given the following Html.ActionLink:
#Html.ActionLink(Model.dsResults.Tables[0].Rows[i]["title"].ToString(), "ItemLinkClick",
new { itemListID = #Model.dsResults.Tables[0].Rows[i]["ItemListID"], itemPosNum = i+1 }, ...
Data from the model contains HTML in the title field. However, I am unable to display the HTML encoded values. ie. underlined text shows up with the <u>....</u> around it.
I've tried Html.Raw in the text part of the ActionLink, but no go.
Any suggestions?
If you still want to use a helper to create an action link with raw HTML for the link text then I don't believe you can use Html.ActionLink. However, the answer to this stackoverflow question describes creating a helper which does this.
I would write the link HTML manually though and use the Url.Action helper which creates the URL which Html.ActionLink would have created:
<a href="#Url.Action("ItemLinkClick", new { itemListID = #Model.dsResults.Tables[0].Rows[i]["ItemListID"], itemPosNum = i+1 })">
#Html.Raw(Model.dsResults.Tables[0].Rows[i]["title"].ToString())
</a>
MVCHtmlString.Create should do the trick.
Using the actionlink below you do not need to pass html in the model. Let the css class or inline style determine how the href is decorated.
#Html.ActionLink(Model.dsResults.Tables[0].Rows[i]["title"], "ItemLinkClick", "Controller", new { #class = "underline", style="text-decoration: underline" }, null)
those are the cases that you should take the other path
#{
string title = Model.dsResults.Tables[0].Rows[i]["title"].ToString(),
aHref = String.Format("/ItemLinkClick/itemListID={0}&itemPosNum={1}...",
Model.dsResults.Tables[0].Rows[i]["ItemListID"],
i+1);
}
#Html.Raw(title)
Remember that Razor helpers, help you, but you can still do things in the HTML way.
You could also use this:
<a class='btn btn-link'
href='/Mycontroler/MyAction/" + item.ID + "'
data-ajax='true'
data-ajax-method='Get'
data-ajax-mode='InsertionMode.Replace'
data-ajax-update='#Mymodal'>My Comments</a>
What is the best way to parse html tag like that:
Results
i just need to extract a href value.
I need to do this on controller.
I know i may use linq to xml for example or regex.
Any ideas what is the better way for that case?
May be there is any MVC helpers ready to go?
Basically what i need to do:
I have my extension method witch returning current url
public static string GetCurrentUrl(this ViewContext context)
{
string action = (string)context.Controller.ValueProvider.GetValue("action").RawValue;
string controller = (string)context.Controller.ValueProvider.GetValue("controller").RawValue;
if (action.ToLower() != "index")
return String.Format("/{0}/{1}", controller, action);
else if (action.ToLower() != "index" && controller.ToLower() != "home")
return String.Format("/{0}", controller);
else
return "/";
}
I need to compare this url with the value from a href like that Results
Use a XML parser and avoid regex. For this specific case XDocument seems easy enough:
var doc = XDocument.Parse("Results");
var href = doc.Element("a").Attribute("href").Value;
For more complex scenarios when HTML specific parsing is required and manipulating the DOM you could use HTML Agility Pack.
parsing html is notoriously difficult, there are so many hidden gotchas. The HTML Agility pack, which is a .NET HTML parsing library. Fizzler enables css selectors for html in c# and is built on top of the agility pack.
I've got the following custom html helper in asp.net mvc 3
public static string RegisterJS(this HtmlHelper helper, ScriptLibrary scriptLib)
{
return "<script type=\"text/javascript\"></script>\r\n";
}
The problem is that the result is getting html encoded like so (I had to add spaces to get so to show the result properly:
<script type="text/javascript"></script>
This obviously isn't much help to me.. Nothing I've read says anything about this.. any thoughts on how I can get my real result back?
You're calling the helper in a Razor # block or an ASPX <%: %> block.
These constructs automatically escape their output.
You need to change the helper to return an HtmlString, which will not be escaped:
return new HtmlString("<script ...");
I want to build a webapplication with a "Single Page Interface", using ASP.NET MVC.
I have searched if this was at least possible and I think the answer is: not by simple means (reading http://msdn.microsoft.com/en-us/magazine/cc507641.aspx#S2 second-last paragraph; that article is from May 2008, though).
I found other examples which implemented this by coding/hacking with jQuery. However, I'm looking for a clean solution, using standard .NET approaches, if possible.
What I want is precisely the same functionality when you create a new "MVC Web Application". However, instead of links to "/Home/About" which reloads the entire page, I want links to "#Home/About" which loads only the new part via AJAX.
The standard approach of calling templates (partial views) with Html.RenderPartial is exactly what I want, only then loading them in through AJAX-requests.
Of course, it might be that I can't use these templates that are rendered by the Master-page for some reason (maybe it's expecting to always be called in a certain context from a certain place or so). But maybe there's another clean solution for how to build your template-pages and fetching them from the Master-page.
Who has a nice solution for implementing such thing, a Single Page Interface?
PS: I'm developing in Visual Web Developer 2008 Express Edition with MVC 1.0 installed, in C#
[edit]
Below I read that working with the templates is possible and that jQuery looks indeed like inevitable, so I tested it.
The following code transforms regular links created by Html.ActionLink into anchor-links (with #) to contain history, and then fetch the page via AJAX and only injecting the html-part I'm interested in (i.e. the partial page inside div#partialView):
$("a").each(function() {
$(this).click(function() {
$("div#partialView").load($(this).attr("href") + " div#partialView");
location.hash = $(this).attr("href");
return false;
});
});
These links also allow for graceful degredation.
But what I have left now, is still fetching the whole page instead of only the partial page. Altering the controller didn't help; it still provided me html of the whole page, with all of these statements:
public ActionResult About()
{
return View();
return View("About");
return PartialView();
return PartialView("About");
}
How could I only return the content of the part I'm interested in (i.e. the contents of Home/About.aspx)?
What I'd like is POSTing a value with AJAX (e.g. "requesttype=ajax") so that my controller knows the page is fetched via AJAX and only returns the partial page; otherwise it will return the whole page (i.e. when you visit /Home/About instead of #Home/About).
Is a good practice to alter Global.asax.cs maybe, to create a new routing schema for AJAX-calls, which will only return partial pages? (I haven't looked into this much, yet.)
[edit2]
Robert Koritnik was right: I also needed an About.ascx page (UserControl) with only the small HTML-content of that page. The first line of About.aspx was linked with the Master-page via MasterPageFile="~/..../Site.master" which caused that all HTML was printed.
But to be able to execute the following in my controller:
public ActionResult About()
{
return Request.IsAjaxRequest() ? (ActionResult)PartialView() : View();
}
I needed to alter the way a PartialView (.ascx file) and a View (.aspx) file was found, otherwise both methods would return the same page (About.aspx, ultimately resulting in an infinite loop).
After putting the following in Global.asax.cs, the correct pages will be returned with PartialView() and View():
protected void Application_Start()
{
foreach (WebFormViewEngine engine in ViewEngines.Engines.Where(c => c is WebFormViewEngine))
{
/* Normal search order:
new string[] { "~/Views/{1}/{0}.aspx",
"~/Views/{1}/{0}.ascx",
"~/Views/Shared/{0}.aspx"
"~/Views/Shared/{0}.ascx"
};
*/
// PartialViews match with .ascx files
engine.PartialViewLocationFormats = new string[] { "~/Views/{1}/{0}.ascx", "~/Views/Shared/{0}.ascx" };
// Views match with .aspx files
engine.ViewLocationFormats = new string[] { "~/Views/{1}/{0}.aspx", "~/Views/Shared/{0}.aspx" };
}
RegisterRoutes(RouteTable.Routes);
}
Full view vs. Partial view
Seems like you've messed up something. If you create an About.aspx page with all the HTML needed to display the whole page it doesn't really matter if you say
return PartialView('About');
The view still returns all the HTML that's written in it.
You should create a separate About.ascx that will only have the content of the page itself without the header and other stuff that's part of the whole page.
Your original page About.aspx will have something like this in its content (to avoid repeating writing the same content twice):
<%= Html.RenderPartial("About") %>
And you can have two controller actions. One that returns a regular view and one that returns a partial view:
return View("About"); // returns About.aspx that holds the content of the About.ascx as well
return PartialView("About"); // only returns the partial About.ascx
Regarding routes in Global.asax
Instead of writing separate routes for Ajax calls you'd rather write an action filter that will work similar as AcceptVerbsAttribute action filter. This way your requests from the client would stay the same (and thus preventing the user from manually requesting wrong stuff), but depending on the request type the correct controller action will get executed.
Well, you can load Partial View through AJAX request. In example, I'll use jquery to make an ajax call.
These could be the action in controller (named HomeController):
public ActionResult About()
{
//Do some logic...
//AboutView is the name of your partial view
return View("AboutView");
}
JQuery ajax call to place the retured html in place you want:
var resultDiv = $('#contentDIV');
$.ajax({
type: "POST",
url: "/Home/About",
success: function(responseHTML) {
resultDiv.replaceWith(responseHTML);
}
});
[edit-question is updated]
It is possible to do exactly what you want. First controller action can give you back the partial view, so mine "AboutView" could have been something like this:
<table>
<tr>
<th>
Column1Header
</th>
<th>
Column2Header
</th>
</tr>
<tr>
<td>
...
</td>
<td>
...
</td>
</tr>
and this HTML is exactly what are you going to have in responseHTML on success handler in jquery ajax method.
Second, you can distinguish in controller action if the request is an ajax request:
public ActionResult About()
{
//partial AboutView is returned if request is ajax
if (Request.IsAjaxRequest())
return View("AboutView");
else //else it will be the default view (page) for this action: "About"
return View();
}
We've got a site that does exactly this, and you really want to use the jQuery route here--alot easier to implement in the long run. And you can easily make it gracefully degrade for users who don't have javascript enabled--like google.
it isn't all that clear what are you asking for, is it for a complete example or for some specific functionality? You should be able to do this without JQuery for simple scenarios, you can use the Ajax view helpers like the ActionLink method. Also, I don't really understand what is your issue with RenderPartial, but maybe you're looking for something like RenderAction from ASP.NET MVC Futures.
ASP.NET MVC 4 (now in beta) adds support for Single Page Applications in MVC.
http://www.asp.net/single-page-application
UPDATE:
...and they removed it from the MVC 4 RC
UPDATE:
...and it is back with the 2012 Fall update