I am using asp.net MVC 4, I'd like to do something like this in my view
my link
I don't like it. Is there a way I can have the namespace implicit? Can I not pass in Viewbag and grab it somehow like global.request.current.viewbag?
If it helps I don't need TheFunctionIUseAlot to be static. I just need it to be easily callable in all my views and hopefully i'd like to not pass in viewbag. The reason I pass viewbag is because i need something in the controller which i stuck in viewbag as well. Maybe i can put it in the model but i don't want the same problem where i am passing model instead of viewbag
You can make the namespace implicit by adding #using NamespaceHere; at the top of your view, or by registering it as a namespace in the views web config. Something like this:
<system.web.webPages.razor>
<host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<pages pageBaseType="System.Web.Mvc.WebViewPage">
<namespaces>
<add namespace="System.Web.Mvc" />
<add namespace="System.Web.Mvc.Ajax" />
<add namespace="System.Web.Mvc.Html" />
<add namespace="System.Web.Routing" />
<add namespace="NamespaceHere"/>
</namespaces>
</pages>
</system.web.webPages.razor>
You can get access to the viewbag in your function if you use a custom page base type for your views. You can find instructions on doing that here: http://haacked.com/archive/2011/02/21/changing-base-type-of-a-razor-view.aspx.
In your situation, to get access to the ViewBag you will want to define your FunctionThatIUseALot in a non-static class that takes a WebViewPage as a constructor parameter (either as dynamic or as a ViewDataDictionary). Then, in your WebViewPage's InitHelpers override, you can create your helper class, passing in this. That will give you access to all of the standard properties of the WebViewPage.
Something like this:
public class Utils {
private WebViewPage page;
public Utils(WebViewPage page) { this.page = page; }
public FunctionThatIUseALot(string someParameter) {
string someViewBagValue = page.ViewBag.SomeViewBagValue;
}
}
public abstract class CustomWebViewPage : WebViewPage {
public Utils Utils { get; set; } // Utils is your helper class
public override void InitHelpers() {
base.InitHelpers();
Utils = new Utils(this);
}
}
The above is not everything you need to do to make it work, you will need to read the article for the rest. But the end result should be that you can just call #Utils.FunctionThatIUseALot("some value") directly in your views.
Note: you will need to do this twice - once for the standard WebViewPage base class, and one for the WebViewPage<TModel> base class.
Related
I have the following problem in my MVC 5 web app. I used database first approach and the entity framwork to create a table [accountlist] that has a foreign key relationship on [UserId] to the [Id] column from [AspNetUsers]. Right now the pertaining accountlist.cshtml contains a dropdown menu. I also tried #Html.HiddenFor(model => model.UserId, new { #Value = HttpContext.Current.User.Identity.Name}) but the problem is how that I need the correct userid and not the username (I don't want the [UserName] from [AspNetUsers] to be an primary key).
Unfortunately, HttpContext.Current.User.Identity.GetUserId() as suggested in this solution says that Identity contains no definition for GetUserId().
Does anyone has solution?
Thanks in advance!
#stephen.vakil is correct. You need to import the namespace. Specifically, you need to add:
#using Microsoft.AspNet.Identity
#model Namespace.To.Foo
Alternatively, if you want to do this more often or just don't want to include the namespace in the view, you can edit the Web.config in the Views folder of your project and add it there instead:
<?xml version="1.0"?>
<configuration>
...
<system.web.webPages.razor>
...
<pages pageBaseType="System.Web.Mvc.WebViewPage">
<namespaces>
<add namespace="System.Web.Mvc" />
<add namespace="System.Web.Mvc.Ajax" />
<add namespace="System.Web.Mvc.Html" />
<add namespace="System.Web.Optimization" />
<add namespace="System.Web.Routing" />
<add namespace="Microsoft.AspNet.Identity" />
Any namespaces there are available to every view automatically.
this is the best Article for asp.net mvc authentication from ben foster. It helped me last time.
It works even if you are not going for entity framework
SigIn Like this
var identity = new ClaimsIdentity(new[] {
new Claim(ClaimTypes.Sid, userID)
},
"ApplicationCookie");
var ctx = Request.GetOwinContext();
var authManager = ctx.Authentication;
authManager.SignIn(identity);
Create New Class
public class AppUser : ClaimsPrincipal
{
public AppUser(ClaimsPrincipal principal)
: base(principal)
{
}
public int ID
{
get
{
return this.FindFirst(ClaimTypes.Sid).Value;
}
}
}
Let's create a custom base view page for our Razor views that provides access to our AppUser principal:
public abstract class AppViewPage<TModel> : WebViewPage<TModel>
{
protected AppUser CurrentUser
{
get
{
return new AppUser(this.User as ClaimsPrincipal);
}
}
}
public abstract class AppViewPage : AppViewPage<dynamic>
{
}
Open up /views/web.config and the set the pageBaseType:
<system.web.webPages.razor>
<pages pageBaseType="NakedIdentity.Mvc.AppViewPage">
Rebuild the project and update the Index.cshtml view:
<p>
User ID: #CurrentUser.ID?
</p>
If you are using SimpleMemberShip provider, then
int UserId = WebSecurity.CurrentUserId;
and add attribute [InitializeSimpleMembership] on the top of controller method.
add this line to your controller constructor:
user = System.Web.HttpContext.Current.GetOwinContext().GetUserManager<ApplicationUserManager>().FindById(System.Web.HttpContext.Current.User.Identity.GetUserId());
then you will have user.Id in all you methods inside your controller. And for security purpose, never keep your user id inside view as hidden!.
I am looking for a way to create a custom extension method for a KendoUI column that will allow me to easily add a css class to the header or the cell itself using an extension method.
Right now i'm using the following to center the contents of both the header and the cell:
columns.Bound(x => x.Value).HeaderHtmlAttributes(new { #class = "cent" }).HtmlAttributes(new { #class = "cent" });
where the cent css class is:
.cent { text-align:center; }
To me this seems like alot of code to write for something this simple.
What i am looking for is a solution to create a custom column builder extension method where i can just do something like this:
columns.Bound(x => x.Value).CenterHeader().CenterCell();
Where the CenterHeader() and CenterCell() would be custom extension methods that would add this css class to the header and cell respectively. The code would look much cleaner if this were possible IMO.
Does anyone know a way to do this?
Why not just create these extensions?
using Kendo.Mvc.UI.Fluent;
namespace MyNamespace
{
public static class MyExtensions
{
public static GridTemplateColumnBuilder<T> CenterHeader<T>(this GridTemplateColumnBuilder<T> builder) where T : class
{
return builder.HeaderHtmlAttributes(new { #class = "cent" });
}
.....
}
}
And add this namespace (so that you shouldn't import it all the time) in Views/web.config:
<system.web.webPages.razor>
<host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<pages pageBaseType="System.Web.Mvc.WebViewPage">
<namespaces>
......
<add namespace="Kendo.Mvc.UI"/>
<add namespace="MyNamespace"/>
......
</namespaces>
</pages>
</system.web.webPages.razor>
When im trying to use my aspx file
#using PagedList.Mvc;
...
#Html.PagedListPager(ViewBag.test, page => Url.Action("Test", new { page })).
I'll get this error message
'System.Web.Mvc.HtmlHelper<dynamic>' has no applicable method named 'PagedListPager' 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.
My .cs file the code look like this
using PagedList;
private List<Quality> Qualitys()
{
List<Quality> Qualitys = new List<Quality>()
{
new Quality(){ID=1,Name="All Qualitys"},
new Quality(){ID=2,Name="1"},
new Quality(){ID=3,Name="2"},
new Quality(){ID=4,Name="3"},
new Quality(){ID=5,Name="4"},
new Quality(){ID=6,Name="5"}
};
return Qualitys;
}
public ActionResult Test(int? page)
{
int pageSize = 3;
int pageNumber = page ?? 1;
ViewBag.test = Qualitys().ToPagedList(pageNumber, pageSize);
return View();
}
In my ~Views/Web.config file I'll have there.
<namespaces>
<add namespace="System.Web.Mvc" />
<add namespace="System.Web.Mvc.Ajax" />
<add namespace="System.Web.Mvc.Html" />
<add namespace="System.Web.Optimization"/>
<add namespace="System.Web.Routing" />
<add namespace="Web" />
</namespaces>
I cant see why Im getting this error, please help.
You need to cast dynamic properties (in this case ViewBag.test) to the required type. it should be
#Html.PagedListPager((IPagedList)ViewBag.test, page => Url.Action("Test", new { page }))
I'm trying to find a way to transform my index.cshtml file when building my project.
For instance make this:
<script src="app-dev.js"></script>
become this when Build mode is Release:
<script src="app-prod.js></script>
Ok, this will work.
Add an appsetting for it:
<add key="Environment" value="dev"/>
Then in your view add this:
<script src="app-#(System.Web.Configuration.WebConfigurationManager.AppSettings["Environment"]).js></script>
In your other environments simply use transforms to replace it i.e.
<appSettings>
<add key="Environment" value="prod" xdt:Transform="SetAttributes" xdt:Locator="Match(key)" />
</appSettings>
An alternative and I feel a better approach would be to abstract out the WebConfiguration manager as an interface and have the app setting set in a model instead.
If it is in a common layout and set everytime maybe create a base model and have it set in an OnActionExecuted in a base controller instead.
In our case the decision has to be made based on whether the build is debug build or release build. We created a mvc helper extension method as
public static MvcHtmlString CustomScriptTag(this HtmlHelper helper)
{
var scriptString = string.Format("<script type='text/javascript' src='{0}'></script>", VirtualPathUtility.ToAbsolute("~/app-prod.js"));
#if DEBUG
scriptString = string.Format("<script type='text/javascript' src='{0}'></script>", VirtualPathUtility.ToAbsolute("~/app-dev.js"));
#endif
return new MvcHtmlString(scriptString);
}
From your cshtml file you can call it like
#Html.CustomScriptTag()
I am trying to use a http hadler, so I created a class lirary project and added this code:
namespace MyProject.Handlers
{
public class Class1 : IHttpHandler
{
public bool IsReusable
{
get { return false; }
}
public void ProcessRequest(HttpContext context)
{
context.Response.Write("Hello from custom handler.");
}
}
}
Then I compiled it and it generated the MyProject.Handlers.dll file. I put it in my asp.net bin folder and added this to the asp.net
<system.webServer>
<handlers>
<add name="TutorialHandler" verb="*" path="*" type="MyProject.Handlers.Class1, MyProject.Handlers" modules="IsapiModule" scriptProcessor="c:\Windows\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" resourceType="File" />
</handlers>
<modules runAllManagedModulesForAllRequests="true">
//some stuff I *think* it doesn't make a difference
</modules>
//some stuff I *think* it doesn't make a difference
</system.webServer>
and
<system.web>
<httpHandlers>
<add verb="*" path="*" type="MyProject.Handlers.Class1, MyProject.Handlers" />
</httpHandlers>
</system.web>
But it just doesn't get called!
I start the debugger, set the breakpoint, but it doesn't stop. If I check the output html in firebug, the sentence "Hello from custom handler" is not there.
What am I doing wrong?
Thanks,
Oscar
EDIT: I'm using framework 4.0, IIS7.
Could it be that I am using routes? (not calling directly index.aspx, but /home or something like this?)
For some reason it wasn't being called when it was at the end of the handlers list. I moved to the top and got a strange error regarding webresources.axd. The reson was the path="*".
I couldn't find a matching path because I am using routes.
At the end I found out that I was using the wrong tool: the modules were the right thing for me, not handlers, because I would like to add things to my output depending on the case. So I changed my approach to use modules instead and it now looks good.
Thanks to all that helped me with comments!