I'm trying to create a HtmlExtension to retrieve the name of the current view.
However, I don't want to have the requested view (e.g. "LogOn" for "/Account/LogOn") but the actual file that is being processed (e.g. "_Layout").
The closest I could find was html.ViewDataContainer.ToString() which returns {ASP._Page_Views_Shared__Layout_cshtml} for example, but I don't think that parsing this would be a great idea.
Is this information available in the Html Extension?
Thanks in advance.
You can create an extension like this,
public static string ViewName(this WebViewPage page)
{
return Path.GetFileNameWithoutExtension(page.VirtualPath);
}
then from a razor view,
The view name is: #this.ViewName()
or without extension,
The view name is: #Path.GetFileNameWithoutExtension(VirtualPath)
Related
I think this might be pretty obvious for others but I cannot understand the working of these type of method overloads.
The ones in which we only pass action method name.
How does these #Html.Helpers get the expected controller?
My guesses:
That particular Helper extract it from the HttpContext
this HtmlHelper htmlHelper parameter holds all the information related
to the request.
I am trying to create a custom helper in which user should pass the name of the action method and it magically gets its respective controller.
When I checked the route-values in this HtmlHelper htmlHelper during run-time they showed me this-
{controller, Home}
{action, Index}
{id, null}
When I checked the HttpContext during run-time, it was null.
Expected output should be-
{controller, Device}
{action, Suggest}
{id, null}
If someone can provide behind the curtains working of default #Html.Helpers with examples that will be great.
UPDATE
I did find what I was looking for.
Here is the link to the question and its answer
All Html helpers have access to the HtmlHelper class. That reason is that these helpers are nothing else but extension methods of the HtmlHelper class.
public static class HelperExtensions
{
public static string ControllerName(this HtmlHelper helper)
{
string name = helper.ViewContext.Controller.GetType().Name
return String.Format("<span'>{0}</span>", name);
}
}
}
So everything regarding the current request is there.
View.cshtml
#Html.ControllerName()
I have created a model binder to sanitize string property from malicious input using AntiXssEncoder.HtmlEncode for us to be able to save encoded string without worrying about XSS. So I have made this work, however, the only problem that I'm having and solving is how to Decode string property with AntiXss encoded the value.
The page render this text as see the below:
I want the page to render the text to <test> me instead of the above image. I tried to look to some resource to do this and can make this happen by adding an extension method to a string in the view. But this is tedious I want to set something global that automatically sanitize string properties in the model before rendering them on the page.
Could anyone suggest a way implement auto string sanitization globally or override the view model and check for string properties and sanitize them before rendering the page?
Update:
Or a way which I could override this part of ActionResult
public ActionResult Test()
{
return View(model);
}
The fact that your code isn't decoding it will depend on how you are implementing your model binder.
To decode you would normally just use HttpUtility.Decode, so you may have to run this somewhere.
It may be that you need to put the [AllowHtml] attribute onto your model properties.
Alternatively it may be that you need to implement IHtmlString somehow to make use of the ToHtmlString() method which lets you put html directly onto the page without MVC sanitising it automatically.
Possibly some more code would make it clearer but one of those three should point you in the right direction.
This question is related to this one, but I think in my example I have detail which may alter answers.
Say I have a User action on a Controller that renders a View for displaying data about a particular User, it might have a UserViewModel like so:
public class UserViewModel {
public string FirstName;
public string LastName;
etc...
}
However, in this View, as well as showing this user data, I want to have a search textbox for the user so they can look up another user on this page. This form would post into an action of FindUser, which accepts the following model:
public class FindUserInputViewModel {
[Required]
public string SearchQuery;
}
If this action finds the model to be invalid, it redirects back to the User action, maintaining the ModelState.
Now, currently to show the validation error, I cannot use a strongly-typed helper as that search query property isn't in UserViewModel, I'd have to do this:
#Html.TextBox("SearchQuery")
#Html.ValidationMessageFor("SearchQuery")
This works, and the error will be displayed, as well as the old value that was POSTed being shown (as it is persisted in the ModelState). However, I'd prefer to use a strongly-typed helper wherever possible.
From all the examples I have seen, the pattern here seems to be that the UserViewModel should contain the FindUserInputViewModel inside it, perhaps as an FindUserInput property. I could then do:
#Html.TextBoxFor(m => m.FindUserInput.SearchQuery)
This also works, as long as I make sure my FindUser action binds to the correct prefix, or I specify a name in the TextboxFor method call.
However, I don't really see why my UserViewModel should contain this other ViewModel simply for the case of binding the validation using this helper. Does it bring other benefits that I am not seeing? I understand the use of it if your View's model is needing to render out the same data you are posting, such as on a typical Edit action, but that isn't the case here.
It looks like to me that what would be handy here is a another generic helper that can reference a different type, something like this:
#Html.TextBoxForType<FindUserInput>(m => m.SearchQuery)
This doesn't exist, but I think I should be able to write that, and this is a good case for one. Does that sound like an appropriate solution, or am I missing something here?
Another option entirely is perhaps that the small-form for posting in that FindUserInputViewModel should have its own GET action as well as POST, and then the User View can just call into it using #Html.Action. It could then render a partial-view that is only strongly typed to FindUserInputViewModel.
Why not create a partial view for your search and simply pass this a new FindUserInputViewModel from your user view?
#Html.Partial("FindUser", new FindUserInputViewModel())
You can type your partial view to FindUserInputViewModel and use strongly-typed helpers in there. I'd say this is the simplest and neatest approach, unless there's something I'm missing?
I'm building a state machine which display different action controls (partial views) on the page according to some dynamic value.
I started writing HtmlHelper Extension methods to ouput the proper html for each state. Something like:
#if(Model.state == "NEW") {
Html.RenderActionEdit()
Html.RenderActionDelete()
}
And to do this I was doing simple methods in the form:
return MvcHtmlString.Create("<form><input>..... </form>");
But this is rather cumbersome for large bits of html. So, the question is, would it be possible to write this Html on separate views (cshtml files) and then somehow load them and pass the result to MvcHtmlString? Like
return MvcHtmlString.Create(View.Load("EditAction.csthml"));
I couldn't find a way to load an existing view and then just "include" it on the partial method's output.
Many thanks for any help!
There are a couple of ways to do this:
#Html.RenderPartial("thepartial.cshtml", model); will pass model to the partial view, and render it. There are a couple of other versions too.
#Html.Action("action", "controller", id) (see msdn) will pass id to the specified action method, and render the view it outputs. This is very convenient if you don't have the model object needed for the partial available in your main view.
In an extension method on HtmlHelper, you could use it like this:
public HtmlString YourContent(this HtmlHelper helper)
{
return helper.Action("action", "controller", new { id = 1 });
}
which in your view would be used by calling #Html.YourContent().
All my dynamically generated action links etc. are creating links like /Account/Setup. It looks strange.
I'd like all my links to be lowercase (meaning /account/setup). Any way to do this?
There is simpler solution in .NET Framework 4.5, a new property RouteCollection.LowercaseUrls, here's an example
Take a look at http://goneale.com/2008/12/19/lowercase-route-urls-in-aspnet-mvc/. You can find more information in another stackoverflow at How can I have lowercase routes in ASP.NET MVC?.
The other posts thus far have not tackled the scenario where you navigate to the root of your web directory. If you have a mapping that directs to the HomeController Index action, you would like the following URL to appear:
mysite/home/ or even mysite/home/index
No amount of Html helper function usage will change the fact that, by default, the following will be shown in the browser location bar:
mysite/Home or mysite/Home/Index
Write an extension method for Html:
public static class MyHtmlExtensions
{
public static string LowerActionLink(this HtmlHelper htmlHelper,someargs)
{
return String.ToLowerInvariant(htmlHelper.ActionLink(someArgs));
}
}
Then use Html.LowerActionLink instead of Html.ActionLink