ASP.Net MVC - Generate an ActionLink from code behind? - asp.net

I have a number of permissions, and based on a set of conditions these permission determine if a user can see certain features. I have written a helper function for this as the logic in the view became quite extensive.
Essentially I'm looking for a function the same as Html.ActionLink that I can access from a class file (Ideally if I can access the Helper that would be great) So I can do somthing like so,
public static string GetAdminLinks()
{
if(PermCheck)
{
return(Html.ActionLink(...));
}
}
Any sugestions?

in controller:
Url.Action("Index", "Home", null, Request.Url.Scheme);

It largely depends on how your permission check is implemented (and of which information it needs to determine the user's permissions). Anyhow, I'd implement it as an extension to the HtmlHelper class.
Somewhere in your App_Code:
using System.Web.Mvc.Html;
public static class HtmlHelperExtensions {
public static string SecureActionLink(this HtmlHelper htmlHelper, string action, string controller){
if(PermCheck)
return htmlHelper.ActionLink(action, controller);
else
return string.Empty;
}
//add other ActionLink overrides if you like...
}
Then you'll be able to call the extension method from anywhere in your ViewPages without any code behind.

Related

Inject SessionExtensions Asp.net Core

I am using the below class named SessionExtensions to set and get complex object (User Class)
public static class SessionExtensions
{
public static void Set<T>(this ISession session, string key, T value)
{
session.SetString(key, JsonSerializer.Serialize(value));
}
public static T Get<T>(this ISession session, string key)
{
var value = session.GetString(key);
return value == null ? default : JsonSerializer.Deserialize<T>(value);
}
}
I am trying to inject it into a view to display the first and last name of a user but all examples are using Session.GetString instead of Get<User>
Thanks
You don't inject a static class. It's just available. That's what static means. In particular, extensions will just naturally appear on the types they extend, as long as they're in an available namespace. That last part is probably your issue. For example, if your extension class is in Namspace.To.My.Extensions, then, in your view (or in _ViewImports.cshtml, you need to add #using Namespace.To.My.Extensions.
You 100% do not need to inject IHttpContextAccessor. A view has built-in access to HttpContext already, since it's part of the request pipeline. Session, in particular, is available directly, as well. So all you need is:
#Session.Get<User>("user_login_credentionals").FirstName
I just found a solution to my questions:
First I have to include and inject the following into my view:
#using Microsoft.AspNetCore.Http
#using MenaProjects.Util
#using MenaProjects.Models
#inject IHttpContextAccessor httpContextAccessor
Then i my html code to access my complex object:
#(httpContextAccessor.HttpContext.Session.Get<User>("user_login_credentionals").FirstName)

How to Link to OData Collection in Razor using ASP.NET MVC Web API OData

I have an ASP.NET MVC 4 app that i'm incorporating an OData API into. This is running the 2012.2 stuff with the larger OData support.
I did not use a separate area for this...that might have been a mistake but my app is small and area seemed overkill.
I've got my controllers setup correctly and an example path to my Segments collection (segments is a type in my domain) is "/odata/Segments". This loads as expected and is working.
On my homepage i'm trying to add a link to this resource using Razor's Html.ActionLink (or RouteLink) but it seems the OData controllers layout doesn't quite work with those methods because the controllers are prefixed with "odata" when registered in WebAPIConfig:
config.Routes.MapODataRoute("OData Route", "odata", model );
I can trick the method to construct the correct url by pretending there's an odata controller when there certainly isn't one (as far as i know) with something like this:
#Html.RouteLink("Segments", "Segments", "odata")
but that seems like a hack.
I don't quite understand the ASP.NET routing plumbing well enough to understand how that prefix passed to MapODataRoute is being incorporated into the MVC chain so that i can use the "right" razor method the "right" way.
just for kicks, here's my SegmentsController:
public class SegmentsController : EntitySetController<Segment, long>
{
private MarketerDB db = new MarketerDB();
// GET api/segments
override public IQueryable<Segment> Get()
{
return db.Segments.AsQueryable();
}
protected override Segment GetEntityByKey(long key)
{
return db.Segments.Find(key);
}
public IQueryable<Affiliate> GetAffiliates([FromODataUri] long key)
{
return this.GetEntityByKey(key).Affiliates.AsQueryable();
}
protected override void Dispose(bool disposing)
{
db.Dispose();
base.Dispose(disposing);
}
}
We have an ODataLink method on System.Web.Http.UrlHelper but we forgot to add one to the MVC System.Web.Mvc.UrlHelper. Till we add it, you can use this extension method,
namespace System.Web.Mvc
{
public static class UrlHelperExtensions
{
private static IODataPathHandler _pathHandler = new DefaultODataPathHandler();
public static string ODataUrl(this UrlHelper urlHelper, string routeName, params ODataPathSegment[] segments)
{
string odataPath = _pathHandler.Link(new ODataPath(segments));
return urlHelper.HttpRouteUrl(
routeName,
new RouteValueDictionary() { { ODataRouteConstants.ODataPath, odataPath } });
}
}
}
and call it from your razor views by doing something like (assuming there is an entityset customers and you want to put the navigation link to orders on customers(42)),
#Url.ODataUrl("odata", new EntitySetPathSegment("customers"), new KeyValuePathSegment("42"), new NavigationPathSegment("orders"))
Make sure you have an #using System.Web.Http.OData.Routing directive in your razor view.

NVelocity extension method ASP.NET webform

I was wondering if it's possible to use an extension method with asp.net webforms and nvelocity. I would like to set some defaults if the string value is null or empty.
Example of .vm file:
Example of my email body...
Billable Status: $billableStatus.Evaluate()
rest of my email body...
Attempted extension method:
public static class Helper
{
public static string Evaluate(this string value)
{
if (String.IsNullOrEmpty(value))
return "Not Provided";
else
return value;
}
}
Or is there an alternative to what I'm tryting to accomplish?
I don't think NVelocity can resolve extension methods with C#/VB.NET syntax sugar. What I do is register an instance of a helper in the velocity context:
var context = VelocityContext();
context.Put("helper", new Helper());
context.Put("billableStatus", "something");
...
and then in your template:
$helper.Evaluate($billableStatus)
You have to make your helper non-static for this to work, of course.
I came across something similar in past and I was looking for something more sophisticated and with more control. I found that NVelocity does provide a way to intercept the method and property calls but for that you will have to implement certain things. In order to make your custom interceptor you will need to implement NVelocity.IDuck. For example
public class MyClass : NVelocity.IDuck
{
public object GetInvoke(string propName)
{
....
}
public object Invoke(string method, params object[] args)
{
....
}
public void SetInvoke(string propName, object value)
{
....
}
}
Now any instance of MyClass will intercept and pass the method and property calls to our these three function implementation and give us a chance to resolve and return the output. You may notice from these three function signatures that in order to implement them we may need some reflection where we can locate respective methods on available extension types and execute them. If needed you can read following blog post for more details about going this way. NVelocity and extension methods

ASP.NET MVC 2.0 JsonRequestBehavior Global Setting

ASP.NET MVC 2.0 will now, by default, throw an exception when an action attempts to return JSON in response to a GET request. I know this can be overridden on a method by method basis by using JsonRequestBehavior.AllowGet, but is it possible to set on a controller or higher basis (possibly the web.config)?
Update: Per Levi's comment, this is what I ended up using-
protected override JsonResult Json(object data, string contentType, System.Text.Encoding contentEncoding)
{
return Json(data, contentType, JsonRequestBehavior.AllowGet);
}
This, like other MVC-specific settings, is not settable via Web.config. But you have two options:
Override the Controller.Json(object, string, Encoding) overload to call Json(object, string, Encoding, JsonRequestBehavior), passing JsonRequestBehavior.AllowGet as the last argument. If you want this to apply to all controllers, then do this inside an abstract base controller class, then have all your controllers subclass that abstract class.
Make an extension method MyJson(this Controller, ...) which creates a JsonResult and sets the appropriate properties, then call it from your controller via this.MyJson(...).
There's another option. Use Action Filters.
Create a new ActionFilterAttribute, apply it to your controller or a specific action (depending on your needs). This should suffice:
public class JsonRequestBehaviorAttribute : ActionFilterAttribute
{
private JsonRequestBehavior Behavior { get; set; }
public JsonRequestBehaviorAttribute()
{
Behavior = JsonRequestBehavior.AllowGet;
}
public override void OnResultExecuting(ResultExecutingContext filterContext)
{
var result = filterContext.Result as JsonResult;
if (result != null)
{
result.JsonRequestBehavior = Behavior;
}
}
}
Then apply it like this:
[JsonRequestBehavior]
public class Upload2Controller : Controller
MVC 2 block Json for GET requests for security reasons. If you want to override that behavior, check out the overload for Json that accepts a JsonRequestBehavior parameter.
public ActionResult Index()
{
return Json(data, JsonRequestBehavior.AllowGet)
}
I also got this error when I first use MVC 2.0 using my old code in MVC 1.0. I use fiddler to identify the cause of the error. See the steps on how to troubleshoot it using Fidder -
http://www.rodcerrada.com/post/2011/07/11/jQuery-getJSON()-does-not-tirgger-the-callback-in-ASPNET-MVC-2.aspx
Is this is the security issue MVC2 was trying to address?
http://haacked.com/archive/2009/06/25/json-hijacking.aspx
If so, it seems like the vulnerability is only an issue if you are trying to do a json call to an outside website. If your MVC2 app is only making json calls to your own website (to fill jqgrids for example), shouldn't you be able to safely override the Json call in your base controller to always allow get?
Just change JSON code from :
$.getJson("methodname/" + ID, null, function (data, textStatus)
to:
$.post("methodname/" + ID, null, function (data, textStatus)

How do you get access to the current System.Web.Routing.RequestContext from within a custom helper method in ASP.NET MVC?

I'm writing a helper method for ASP.NET MVC and I need to call Url.Content to get an appropriate URL for the context. However, in order to create a new UrlHelper() I need to get the current RequestContext (System.Web.Routing.RequestContext to be precise) and I'm not sure how to grab it. Anyone know?
If the current IHttpHandler is MvcHandler, you can use
((MvcHandler)HttpContext.Current.Handler).RequestContext
Noticed this was still unanswered. As of MVC 1.0 you can do:
public static string NewHelperMethod(this HtmlHelper helper)
{
UrlHelper url = new UrlHelper(helper.ViewContext.RequestContext);
You may have found an answer elsewhere, but here goes;
In a controller action, you can get to the current RequestContext like so:
public ActionResult SomeAction(){
var helper = new UrlHelper(this.ControllerContext.RequestContext);
...
}
As mentioned above, just extend the HtmlHelper and the context is exposed in that way. For example:
public static string ExtensionMethodName(this HtmlHelper html,object o)
{
html.ViewContext.HttpContext.Request.Uri ... etc
}
Don't create a new one. Just extend the existing UrlHelper, just like you'd extend HtmlHelper:
public static string IdLink(this UrlHelper helper, Guid id)
{ //...
If you must use both HtmlHelper and UrlHelper, pass one of them as a regular (non-"this") argument.

Resources