├── .gitignore
├── LICENSE
├── README.md
├── Settings.StyleCop
├── System.Web.Mvc.Expressions.1.0.6.nupkg
├── System.Web.Mvc.Expressions.sln
├── System.Web.Mvc.Expressions
├── AjaxHelperExtensions.cs
├── ControllerExtensions.cs
├── HtmlHelperExtensions.cs
├── Internals
│ ├── ExpressionHelpers.cs
│ ├── MvcExtensions.cs
│ ├── RouteInformation.cs
│ └── RouteValueDictionaryExtensions.cs
├── ModelStateDictionaryExtensions.cs
├── Properties
│ └── AssemblyInfo.cs
├── System.Web.Mvc.Expressions.csproj
├── System.Web.Mvc.Expressions.ruleset
├── UrlHelperExtensions.cs
└── packages.config
├── logo.png
└── nuget-logo.png
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 |
4 | # User-specific files
5 | *.suo
6 | *.user
7 | *.sln.docstates
8 |
9 | # Build results
10 | [Dd]ebug/
11 | [Dd]ebugPublic/
12 | [Rr]elease/
13 | [Rr]eleases/
14 | x64/
15 | x86/
16 | build/
17 | bld/
18 | [Bb]in/
19 | [Oo]bj/
20 |
21 | # Roslyn cache directories
22 | *.ide/
23 |
24 | # MSTest test Results
25 | [Tt]est[Rr]esult*/
26 | [Bb]uild[Ll]og.*
27 |
28 | #NUNIT
29 | *.VisualState.xml
30 | TestResult.xml
31 |
32 | # Build Results of an ATL Project
33 | [Dd]ebugPS/
34 | [Rr]eleasePS/
35 | dlldata.c
36 |
37 | *_i.c
38 | *_p.c
39 | *_i.h
40 | *.ilk
41 | *.meta
42 | *.obj
43 | *.pch
44 | *.pdb
45 | *.pgc
46 | *.pgd
47 | *.rsp
48 | *.sbr
49 | *.tlb
50 | *.tli
51 | *.tlh
52 | *.tmp
53 | *.tmp_proj
54 | *.log
55 | *.vspscc
56 | *.vssscc
57 | .builds
58 | *.pidb
59 | *.svclog
60 | *.scc
61 |
62 | # Chutzpah Test files
63 | _Chutzpah*
64 |
65 | # Visual C++ cache files
66 | ipch/
67 | *.aps
68 | *.ncb
69 | *.opensdf
70 | *.sdf
71 | *.cachefile
72 |
73 | # Visual Studio profiler
74 | *.psess
75 | *.vsp
76 | *.vspx
77 |
78 | # TFS 2012 Local Workspace
79 | $tf/
80 |
81 | # Guidance Automation Toolkit
82 | *.gpState
83 |
84 | # ReSharper is a .NET coding add-in
85 | _ReSharper*/
86 | *.[Rr]e[Ss]harper
87 | *.DotSettings.user
88 |
89 | # JustCode is a .NET coding addin-in
90 | .JustCode
91 |
92 | # TeamCity is a build add-in
93 | _TeamCity*
94 |
95 | # DotCover is a Code Coverage Tool
96 | *.dotCover
97 |
98 | # NCrunch
99 | _NCrunch_*
100 | .*crunch*.local.xml
101 |
102 | # MightyMoose
103 | *.mm.*
104 | AutoTest.Net/
105 |
106 | # Web workbench (sass)
107 | .sass-cache/
108 |
109 | # Installshield output folder
110 | [Ee]xpress/
111 |
112 | # DocProject is a documentation generator add-in
113 | DocProject/buildhelp/
114 | DocProject/Help/*.HxT
115 | DocProject/Help/*.HxC
116 | DocProject/Help/*.hhc
117 | DocProject/Help/*.hhk
118 | DocProject/Help/*.hhp
119 | DocProject/Help/Html2
120 | DocProject/Help/html
121 |
122 | # Click-Once directory
123 | publish/
124 |
125 | # Publish Web Output
126 | *.[Pp]ublish.xml
127 | *.azurePubxml
128 | # TODO: Comment the next line if you want to checkin your web deploy settings
129 | # but database connection strings (with potential passwords) will be unencrypted
130 | *.pubxml
131 | *.publishproj
132 |
133 | # The packages folder can be ignored because of Package Restore
134 | **/packages/*
135 | # except build/, which is used as an MSBuild target.
136 | !**/packages/build/
137 | # If using the old MSBuild-Integrated Package Restore, uncomment this:
138 | #!**/packages/repositories.config
139 |
140 | # Windows Azure Build Output
141 | csx/
142 | *.build.csdef
143 |
144 | # Windows Store app package directory
145 | AppPackages/
146 |
147 | # Others
148 | sql/
149 | *.Cache
150 | ClientBin/
151 | [Ss]tyle[Cc]op.*
152 | ~$*
153 | *~
154 | *.dbmdl
155 | *.dbproj.schemaview
156 | *.pfx
157 | *.publishsettings
158 | node_modules/
159 |
160 | # RIA/Silverlight projects
161 | Generated_Code/
162 |
163 | # Backup & report files from converting an old project file
164 | # to a newer Visual Studio version. Backup files are not needed,
165 | # because we have git ;-)
166 | _UpgradeReport_Files/
167 | Backup*/
168 | UpgradeLog*.XML
169 | UpgradeLog*.htm
170 |
171 | # SQL Server files
172 | *.mdf
173 | *.ldf
174 |
175 | # Business Intelligence projects
176 | *.rdl.data
177 | *.bim.layout
178 | *.bim_*.settings
179 |
180 | # Microsoft Fakes
181 | FakesAssemblies/
182 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2014 Ivaylo Kenov
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
ASP.NET-MVC-Lambda-Expression-Helpers - Typed
link generation for ASP.NET MVC
2 | =====================================
3 | Extension methods allowing using Lambda Expressions instead of magic strings in your ASP.NET MVC 5 application. It resolves all route values, including areas and parameters in the method expression.
4 |
5 | [](https://ci.appveyor.com/project/ivaylokenov/asp-net-mvc-lambda-expression-helpers) [](https://github.com/ivaylokenov/ASP.NET-MVC-Lambda-Expression-Helpers/blob/master/LICENSE) [](https://www.nuget.org/packages/System.Web.Mvc.Expressions/)
6 |
7 | To install from NuGet:
8 |
9 | Install-Package System.Web.Mvc.Expressions
10 |
11 | For other interesting packages check out:
12 |
13 | - [MyTested.AspNetCore.Mvc](https://github.com/ivaylokenov/MyTested.AspNetCore.Mvc) - fluent testing framework for ASP.NET Core MVC
14 | - [MyTested.WebApi](https://github.com/ivaylokenov/MyTested.WebApi) - fluent testing framework for ASP.NET Web API 2
15 | - [MyTested.HttpServer](https://github.com/ivaylokenov/MyTested.HttpServer) - fluent testing framework for remote HTTP servers
16 | - [AspNet.Mvc.TypedRouting](https://github.com/ivaylokenov/AspNet.Mvc.TypedRouting) - typed routing and link generation for ASP.NET MVC 6
17 |
18 | Currently supported in Controller (add "using System.Web.Mvc.Expressions;"):
19 |
20 | ```
21 | - RedirectToAction(c => c.Index())
22 |
23 | - RedirectToActionPermanent(c => c.Index())
24 |
25 | - AddModelError(m => m.Bar, "Invalid value for Bar.")
26 |
27 | - AddModelError(m => m.Baz, new ArgumentException("Invalid value for Baz.")
28 | ```
29 |
30 | Currently supported in Views (add namespace "System.Web.Mvc.Expressions" to the web.config file in the Views folder):
31 | ```
32 | - Html.ActionLink(c => c.Index(5))
33 |
34 | - Html.BeginForm(c => c.Index(5))
35 |
36 | - Html.RenderAction(c => c.Index(5))
37 |
38 | - Html.Action(c => c.Index(5))
39 |
40 | - Url.Action(c => c.Index(5))
41 |
42 | - Ajax.ActionLink(c => c.Index(5))
43 |
44 | - Ajax.BeginForm(c => c.Index(5))
45 | ```
46 | More info:
47 | - Support for areas out of the box.
48 | - Support for attribute routing - `RouteAttribute`, `RoutePrefixAttribute` and `RouteAreaAttribute`.
49 | - Support for `ActionNameAttribute` which value overrides the action name when generating URL.
50 | - Support for URL generation to async controller actions.
51 |
52 | Authors:
53 |
54 | - [Ivaylo Kenov](https://github.com/ivaylokenov)
55 | - [Vladislav Karamfilov](https://github.com/vladislav-karamfilov)
56 |
57 | Contributors:
58 |
59 | - [Wayne Brantley](https://github.com/waynebrantley)
--------------------------------------------------------------------------------
/Settings.StyleCop:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | False
8 |
9 |
10 |
11 |
12 | False
13 |
14 |
15 |
16 |
17 | False
18 |
19 |
20 |
21 |
22 | False
23 |
24 |
25 |
26 |
27 | False
28 |
29 |
30 |
31 |
32 | False
33 |
34 |
35 |
36 |
37 | False
38 |
39 |
40 |
41 |
42 | False
43 |
44 |
45 |
46 |
47 | False
48 |
49 |
50 |
51 |
52 | False
53 |
54 |
55 |
56 |
57 | False
58 |
59 |
60 |
61 |
62 | False
63 |
64 |
65 |
66 |
67 | False
68 |
69 |
70 |
71 |
72 | False
73 |
74 |
75 |
76 |
77 | False
78 |
79 |
80 |
81 |
82 | False
83 |
84 |
85 |
86 |
87 | False
88 |
89 |
90 |
91 |
92 | False
93 |
94 |
95 |
96 |
97 | False
98 |
99 |
100 |
101 |
102 | False
103 |
104 |
105 |
106 |
107 | False
108 |
109 |
110 |
111 |
112 | False
113 |
114 |
115 |
116 |
117 | False
118 |
119 |
120 |
121 |
122 | False
123 |
124 |
125 |
126 |
127 | False
128 |
129 |
130 |
131 |
132 | False
133 |
134 |
135 |
136 |
137 | False
138 |
139 |
140 |
141 |
142 | False
143 |
144 |
145 |
146 |
147 | False
148 |
149 |
150 |
151 |
152 | False
153 |
154 |
155 |
156 |
157 | False
158 |
159 |
160 |
161 |
162 | False
163 |
164 |
165 |
166 |
167 | False
168 |
169 |
170 |
171 |
172 | False
173 |
174 |
175 |
176 |
177 | False
178 |
179 |
180 |
181 |
182 | False
183 |
184 |
185 |
186 |
187 | False
188 |
189 |
190 |
191 |
192 | False
193 |
194 |
195 |
196 |
197 | False
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 | at
207 | db
208 | or
209 | up
210 | iq
211 | it
212 | un
213 | bg
214 |
215 |
216 |
217 |
218 |
--------------------------------------------------------------------------------
/System.Web.Mvc.Expressions.1.0.6.nupkg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ivaylokenov/ASP.NET-MVC-Lambda-Expression-Helpers/a14a62f5b673454596fb4b9df697b122823deee6/System.Web.Mvc.Expressions.1.0.6.nupkg
--------------------------------------------------------------------------------
/System.Web.Mvc.Expressions.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 14
4 | VisualStudioVersion = 14.0.25420.1
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "System.Web.Mvc.Expressions", "System.Web.Mvc.Expressions\System.Web.Mvc.Expressions.csproj", "{B7CF5FFF-4F16-4FC4-8F5C-871CA14FC473}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Any CPU = Debug|Any CPU
11 | Release|Any CPU = Release|Any CPU
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {B7CF5FFF-4F16-4FC4-8F5C-871CA14FC473}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15 | {B7CF5FFF-4F16-4FC4-8F5C-871CA14FC473}.Debug|Any CPU.Build.0 = Debug|Any CPU
16 | {B7CF5FFF-4F16-4FC4-8F5C-871CA14FC473}.Release|Any CPU.ActiveCfg = Release|Any CPU
17 | {B7CF5FFF-4F16-4FC4-8F5C-871CA14FC473}.Release|Any CPU.Build.0 = Release|Any CPU
18 | EndGlobalSection
19 | GlobalSection(SolutionProperties) = preSolution
20 | HideSolutionNode = FALSE
21 | EndGlobalSection
22 | EndGlobal
23 |
--------------------------------------------------------------------------------
/System.Web.Mvc.Expressions/AjaxHelperExtensions.cs:
--------------------------------------------------------------------------------
1 | namespace System.Web.Mvc.Expressions
2 | {
3 | using System.Linq.Expressions;
4 | using System.Threading.Tasks;
5 | using System.Web.Mvc.Ajax;
6 | using System.Web.Mvc.Expressions.Internals;
7 | using System.Web.Mvc.Html;
8 |
9 | public static class AjaxHelperExtensions
10 | {
11 | public static MvcForm BeginForm(
12 | this AjaxHelper helper,
13 | Expression> action,
14 | object routeValues = null,
15 | AjaxOptions ajaxOptions = null,
16 | object htmlAttributes = null)
17 | where TController : Controller
18 | {
19 | var routeInfo = RouteInformation.FromExpression(action, routeValues);
20 | return helper.BeginForm(
21 | routeInfo.ActionName,
22 | routeInfo.ControllerName,
23 | routeInfo.RouteValueDictionary,
24 | ajaxOptions,
25 | HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
26 | }
27 |
28 | public static MvcForm BeginForm(
29 | this AjaxHelper helper,
30 | Expression> action,
31 | object routeValues = null,
32 | AjaxOptions ajaxOptions = null,
33 | object htmlAttributes = null)
34 | where TController : Controller
35 | {
36 | var routeInfo = RouteInformation.FromExpression(action, routeValues);
37 | return helper.BeginForm(
38 | routeInfo.ActionName,
39 | routeInfo.ControllerName,
40 | routeInfo.RouteValueDictionary,
41 | ajaxOptions,
42 | HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
43 | }
44 |
45 | public static MvcHtmlString ActionLink(
46 | this AjaxHelper helper,
47 | string linkText,
48 | Expression> action,
49 | object routeValues = null,
50 | AjaxOptions ajaxOptions = null,
51 | object htmlAttributes = null)
52 | where TController : Controller
53 | {
54 | var routeInfo = RouteInformation.FromExpression(action, routeValues);
55 | return helper.ActionLink(
56 | linkText,
57 | routeInfo.ActionName,
58 | routeInfo.ControllerName,
59 | routeInfo.RouteValueDictionary,
60 | ajaxOptions,
61 | HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
62 | }
63 |
64 | public static MvcHtmlString ActionLink(
65 | this AjaxHelper helper,
66 | string linkText,
67 | Expression> action,
68 | object routeValues = null,
69 | AjaxOptions ajaxOptions = null,
70 | object htmlAttributes = null)
71 | where TController : Controller
72 | {
73 | var routeInfo = RouteInformation.FromExpression(action, routeValues);
74 | return helper.ActionLink(
75 | linkText,
76 | routeInfo.ActionName,
77 | routeInfo.ControllerName,
78 | routeInfo.RouteValueDictionary,
79 | ajaxOptions,
80 | HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
81 | }
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/System.Web.Mvc.Expressions/ControllerExtensions.cs:
--------------------------------------------------------------------------------
1 | namespace System.Web.Mvc.Expressions
2 | {
3 | using System;
4 | using System.Linq.Expressions;
5 | using System.Threading.Tasks;
6 | using System.Web.Mvc;
7 | using System.Web.Mvc.Expressions.Internals;
8 | using System.Web.Routing;
9 |
10 | public static class ControllerExtensions
11 | {
12 | public static RedirectToRouteResult RedirectToAction(
13 | this TController controller,
14 | Expression> action,
15 | object routeValues = null)
16 | where TController : Controller
17 | {
18 | return GetRedirectFromExpression(action, routeValues);
19 | }
20 |
21 | public static RedirectToRouteResult RedirectToAction(
22 | this TController controller,
23 | Expression> action,
24 | object routeValues = null)
25 | where TController : Controller
26 | {
27 | return GetRedirectFromExpression(action, routeValues);
28 | }
29 |
30 | public static RedirectToRouteResult RedirectToAction(
31 | this Controller controller,
32 | Expression> action,
33 | object routeValues = null)
34 | where TRedirectController : Controller
35 | {
36 | return GetRedirectFromExpression(action, routeValues);
37 | }
38 |
39 | public static RedirectToRouteResult RedirectToAction(
40 | this Controller controller,
41 | Expression> action,
42 | object routeValues = null)
43 | where TRedirectController : Controller
44 | {
45 | return GetRedirectFromExpression(action, routeValues);
46 | }
47 |
48 | public static RedirectToRouteResult RedirectToActionPermanent(
49 | this TController controller,
50 | Expression> action,
51 | object routeValues = null)
52 | where TController : Controller
53 | {
54 | return GetRedirectFromExpression(action, routeValues, true);
55 | }
56 |
57 | public static RedirectToRouteResult RedirectToActionPermanent(
58 | this TController controller,
59 | Expression> action,
60 | object routeValues = null)
61 | where TController : Controller
62 | {
63 | return GetRedirectFromExpression(action, routeValues, true);
64 | }
65 |
66 | public static RedirectToRouteResult RedirectToActionPermanent(
67 | this Controller controller,
68 | Expression> action,
69 | object routeValues = null)
70 | where TRedirectController : Controller
71 | {
72 | return GetRedirectFromExpression(action, routeValues, true);
73 | }
74 |
75 | public static RedirectToRouteResult RedirectToActionPermanent(
76 | this Controller controller,
77 | Expression> action,
78 | object routeValues = null)
79 | where TRedirectController : Controller
80 | {
81 | return GetRedirectFromExpression(action, routeValues, true);
82 | }
83 |
84 | private static RedirectToRouteResult GetRedirectFromExpression(
85 | LambdaExpression action,
86 | object routeValues = null,
87 | bool permanent = false)
88 | where TRedirectController : Controller
89 | {
90 | var routeValuesDictionary = new RouteValueDictionary(routeValues);
91 | routeValuesDictionary.AddRouteValuesFromExpression(action);
92 |
93 | return new RedirectToRouteResult(null, routeValuesDictionary, permanent);
94 | }
95 | }
96 | }
97 |
--------------------------------------------------------------------------------
/System.Web.Mvc.Expressions/HtmlHelperExtensions.cs:
--------------------------------------------------------------------------------
1 | namespace System.Web.Mvc.Expressions
2 | {
3 | using System;
4 | using System.Linq.Expressions;
5 | using System.Threading.Tasks;
6 | using System.Web.Mvc;
7 | using System.Web.Mvc.Expressions.Internals;
8 | using System.Web.Mvc.Html;
9 |
10 | public static class HtmlHelperExtensions
11 | {
12 | public static MvcForm BeginForm(
13 | this HtmlHelper helper,
14 | Expression> action,
15 | FormMethod method,
16 | object routeValues = null,
17 | object htmlAttributes = null)
18 | where TController : Controller
19 | {
20 | var routeInfo = RouteInformation.FromExpression(action, routeValues);
21 | return helper.BeginForm(
22 | routeInfo.ActionName,
23 | routeInfo.ControllerName,
24 | routeInfo.RouteValueDictionary,
25 | method,
26 | HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
27 | }
28 |
29 | public static MvcForm BeginForm(
30 | this HtmlHelper helper,
31 | Expression> action,
32 | FormMethod method,
33 | object routeValues = null,
34 | object htmlAttributes = null)
35 | where TController : Controller
36 | {
37 | var routeInfo = RouteInformation.FromExpression(action, routeValues);
38 | return helper.BeginForm(
39 | routeInfo.ActionName,
40 | routeInfo.ControllerName,
41 | routeInfo.RouteValueDictionary,
42 | method,
43 | HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
44 | }
45 |
46 | public static MvcHtmlString ActionLink(
47 | this HtmlHelper helper,
48 | string linkText,
49 | Expression> action,
50 | object routeValues = null,
51 | object htmlAttributes = null)
52 | where TController : Controller
53 | {
54 | var routeInfo = RouteInformation.FromExpression(action, routeValues);
55 | return helper.ActionLink(
56 | linkText,
57 | routeInfo.ActionName,
58 | routeInfo.ControllerName,
59 | routeInfo.RouteValueDictionary,
60 | HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
61 | }
62 |
63 | public static MvcHtmlString ActionLink(
64 | this HtmlHelper helper,
65 | string linkText,
66 | Expression> action,
67 | object routeValues = null,
68 | object htmlAttributes = null)
69 | where TController : Controller
70 | {
71 | var routeInfo = RouteInformation.FromExpression(action, routeValues);
72 | return helper.ActionLink(
73 | linkText,
74 | routeInfo.ActionName,
75 | routeInfo.ControllerName,
76 | routeInfo.RouteValueDictionary,
77 | HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
78 | }
79 |
80 | public static void RenderAction(
81 | this HtmlHelper helper,
82 | Expression> action,
83 | object routeValues = null)
84 | where TController : Controller
85 | {
86 | var routeInfo = RouteInformation.FromExpression(action, routeValues);
87 | helper.RenderAction(routeInfo.ActionName, routeInfo.ControllerName, routeInfo.RouteValueDictionary);
88 | }
89 |
90 | public static void RenderAction(
91 | this HtmlHelper helper,
92 | Expression> action,
93 | object routeValues = null)
94 | where TController : Controller
95 | {
96 | var routeInfo = RouteInformation.FromExpression(action, routeValues);
97 | helper.RenderAction(routeInfo.ActionName, routeInfo.ControllerName, routeInfo.RouteValueDictionary);
98 | }
99 |
100 | public static MvcHtmlString Action(
101 | this HtmlHelper helper,
102 | Expression> action,
103 | object routeValues = null)
104 | where TController : Controller
105 | {
106 | var routeInfo = RouteInformation.FromExpression(action, routeValues);
107 | return helper.Action(routeInfo.ActionName, routeInfo.ControllerName, routeInfo.RouteValueDictionary);
108 | }
109 |
110 | public static MvcHtmlString Action(
111 | this HtmlHelper helper,
112 | Expression> action,
113 | object routeValues = null)
114 | where TController : Controller
115 | {
116 | var routeInfo = RouteInformation.FromExpression(action, routeValues);
117 | return helper.Action(routeInfo.ActionName, routeInfo.ControllerName, routeInfo.RouteValueDictionary);
118 | }
119 | }
120 | }
121 |
--------------------------------------------------------------------------------
/System.Web.Mvc.Expressions/Internals/ExpressionHelpers.cs:
--------------------------------------------------------------------------------
1 | namespace System.Web.Mvc.Expressions.Internals
2 | {
3 | using System.Collections.Generic;
4 | using System.Linq.Expressions;
5 | using System.Reflection;
6 |
7 | public static class ExpressionHelpers
8 | {
9 | public static object GetArgumentValue(Expression argumentExpression)
10 | {
11 | object argumentValue;
12 | if (argumentExpression.NodeType == ExpressionType.Constant)
13 | {
14 | argumentValue = ((ConstantExpression)argumentExpression).Value;
15 | }
16 | else
17 | {
18 | var typeConversionExpression = Expression.Convert(argumentExpression, typeof(object));
19 | argumentValue = Expression.Lambda>(typeConversionExpression, null).Compile().Invoke();
20 | }
21 |
22 | return argumentValue;
23 | }
24 |
25 | public static string GetExpressionText(LambdaExpression expression)
26 | {
27 | var result = string.Empty;
28 | if (expression.Body.NodeType == ExpressionType.Convert)
29 | {
30 | var unaryExpression = expression.Body as UnaryExpression;
31 | if (unaryExpression != null)
32 | {
33 | result = string.Join(".", GetProperties(unaryExpression.Operand));
34 | }
35 | }
36 | else
37 | {
38 | result = ExpressionHelper.GetExpressionText(expression);
39 | }
40 |
41 | return result;
42 | }
43 |
44 | public static void ValidatePropertyOrIndexerExpression(LambdaExpression expression)
45 | {
46 | if (expression == null)
47 | {
48 | throw new ArgumentNullException(nameof(expression));
49 | }
50 |
51 | var isValid = false;
52 |
53 | if (expression.Body.NodeType == ExpressionType.Convert)
54 | {
55 | var unaryExpression = expression.Body as UnaryExpression;
56 |
57 | isValid = unaryExpression != null &&
58 | (unaryExpression.Operand is MemberExpression ||
59 | (unaryExpression.Operand is MethodCallExpression &&
60 | IsSingleArgumentIndexer((MethodCallExpression)unaryExpression.Operand)));
61 | }
62 | else if (expression.Body.NodeType == ExpressionType.Call)
63 | {
64 | var methodExpression = expression.Body as MethodCallExpression;
65 |
66 | isValid = IsSingleArgumentIndexer(methodExpression);
67 | }
68 | else if (expression.Body.NodeType == ExpressionType.MemberAccess)
69 | {
70 | var memberExpression = expression.Body as MemberExpression;
71 |
72 | isValid = memberExpression?.Member is PropertyInfo;
73 | }
74 |
75 | if (!isValid)
76 | {
77 | throw new ArgumentOutOfRangeException(
78 | nameof(expression),
79 | $"{nameof(expression)} should refer to a property or indexer.");
80 | }
81 | }
82 |
83 | private static bool IsSingleArgumentIndexer(MethodCallExpression methodExpression)
84 | {
85 | if (methodExpression != null && methodExpression.Arguments.Count == 1)
86 | {
87 | var methodDeclaringTypeDefaultMembers = methodExpression.Method.DeclaringType.GetDefaultMembers();
88 | for (int i = 0; i < methodDeclaringTypeDefaultMembers.Length; i++)
89 | {
90 | var property = methodDeclaringTypeDefaultMembers[i] as PropertyInfo;
91 | if (property?.GetGetMethod() == methodExpression.Method)
92 | {
93 | return true;
94 | }
95 | }
96 | }
97 |
98 | return false;
99 | }
100 |
101 | private static IEnumerable GetProperties(Expression expression)
102 | {
103 | var memberExpression = expression as MemberExpression;
104 | if (memberExpression == null)
105 | {
106 | var methodExpression = expression as MethodCallExpression;
107 | if (methodExpression != null && IsSingleArgumentIndexer(methodExpression))
108 | {
109 | var indexerMemberExpression = methodExpression.Object as MemberExpression;
110 | if (indexerMemberExpression != null)
111 | {
112 | var index = GetArgumentValue(methodExpression.Arguments[0]);
113 |
114 | var propertyName = string.Format(
115 | "{0}.{1}[{2}]",
116 | string.Join(".", GetProperties(indexerMemberExpression.Expression)),
117 | indexerMemberExpression.Member.Name,
118 | index);
119 |
120 | yield return propertyName.TrimStart('.');
121 | }
122 | }
123 |
124 | yield break;
125 | }
126 |
127 | foreach (var propertyInfo in GetProperties(memberExpression.Expression))
128 | {
129 | yield return propertyInfo;
130 | }
131 |
132 | var property = memberExpression.Member as PropertyInfo;
133 | if (property != null)
134 | {
135 | yield return property.Name;
136 | }
137 | }
138 | }
139 | }
140 |
--------------------------------------------------------------------------------
/System.Web.Mvc.Expressions/Internals/MvcExtensions.cs:
--------------------------------------------------------------------------------
1 | namespace System.Web.Mvc.Expressions.Internals
2 | {
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Linq.Expressions;
6 | using System.Reflection;
7 | using System.Collections.Concurrent;
8 |
9 | public static class MvcExtensions
10 | {
11 | private const string ControllerSuffix = "Controller";
12 |
13 | private static ConcurrentDictionary ActionNameInfo = new ConcurrentDictionary();
14 |
15 | public static string GetActionName(this LambdaExpression actionExpression)
16 | {
17 | var methodCallExpression = actionExpression.Body as MethodCallExpression;
18 | if (methodCallExpression?.Object == null)
19 | {
20 | throw new ArgumentOutOfRangeException(
21 | nameof(actionExpression),
22 | "Expected instance method call expression but received other type of expression instead.");
23 | }
24 |
25 | var actionMethod = methodCallExpression.Method;
26 | string result;
27 | if (ActionNameInfo.TryGetValue(actionMethod, out result))
28 | {
29 | return result;
30 | }
31 |
32 | var actionNameAttribute = actionMethod.GetCustomAttribute();
33 | result = actionNameAttribute?.Name ?? actionMethod.Name;
34 | ActionNameInfo.TryAdd(actionMethod, result);
35 | return result;
36 | }
37 |
38 | public static string GetControllerName(this Type controllerType)
39 | {
40 | string typeName = controllerType.Name;
41 | return typeName.Substring(0, typeName.Length - ControllerSuffix.Length);
42 | }
43 |
44 | private static ConcurrentDictionary RouteAreaInfo = new ConcurrentDictionary();
45 |
46 | public static string GetAreaName(this Type type)
47 | {
48 | string result;
49 | if (RouteAreaInfo.TryGetValue(type, out result))
50 | {
51 | return result;
52 | }
53 |
54 | var routeAreaAttribute = type.GetCustomAttribute();
55 | if (routeAreaAttribute != null)
56 | {
57 | RouteAreaInfo.TryAdd(type, routeAreaAttribute.AreaName);
58 | return routeAreaAttribute.AreaName;
59 | }
60 |
61 | string[] namespaceParts = (type.Namespace ?? string.Empty).ToLowerInvariant().Split('.');
62 | int areaIndex = GetAreaIndex(namespaceParts);
63 | result = areaIndex < 0 ? string.Empty : namespaceParts[areaIndex + 1];
64 | RouteAreaInfo.TryAdd(type, result);
65 | return result;
66 | }
67 |
68 | private static int GetAreaIndex(IReadOnlyList namespaceParts)
69 | {
70 | for (int i = 0; i < namespaceParts.Count; i++)
71 | {
72 | if (namespaceParts[i] == "areas")
73 | {
74 | return i;
75 | }
76 | }
77 |
78 | return -1;
79 | }
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/System.Web.Mvc.Expressions/Internals/RouteInformation.cs:
--------------------------------------------------------------------------------
1 | namespace System.Web.Mvc.Expressions.Internals
2 | {
3 | using System.Linq.Expressions;
4 | using System.Web.Mvc;
5 | using System.Web.Routing;
6 |
7 | public class RouteInformation
8 | {
9 | public RouteInformation(string actionName, string controllerName, RouteValueDictionary routeValueDictionary)
10 | {
11 | this.ActionName = actionName;
12 | this.ControllerName = controllerName;
13 | this.RouteValueDictionary = routeValueDictionary;
14 | }
15 |
16 | public string ActionName { get; set; }
17 |
18 | public string ControllerName { get; set; }
19 |
20 | public RouteValueDictionary RouteValueDictionary { get; set; }
21 |
22 | public static RouteInformation FromExpression(LambdaExpression action, object routeValues = null)
23 | where TController : Controller
24 | {
25 | string actionName = action.GetActionName();
26 |
27 | var controllerType = typeof(TController);
28 | string controllerName = controllerType.GetControllerName();
29 |
30 | var routeValueDictionary = new RouteValueDictionary(routeValues);
31 | routeValueDictionary.ProcessParameters(action);
32 | routeValueDictionary.ProcessArea(controllerType);
33 |
34 | var routeInformation = new RouteInformation(actionName, controllerName, routeValueDictionary);
35 | return routeInformation;
36 | }
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/System.Web.Mvc.Expressions/Internals/RouteValueDictionaryExtensions.cs:
--------------------------------------------------------------------------------
1 | namespace System.Web.Mvc.Expressions.Internals
2 | {
3 | using System;
4 | using System.Linq.Expressions;
5 | using System.Web.Mvc;
6 | using System.Web.Routing;
7 |
8 | public static class RouteValueDictionaryExtensions
9 | {
10 | public static void AddRouteValuesFromExpression(
11 | this RouteValueDictionary routeValueDictionary,
12 | LambdaExpression action)
13 | where TController : Controller
14 | {
15 | var type = typeof(TController);
16 |
17 | routeValueDictionary.ProcessArea(type);
18 | routeValueDictionary.ProcessController(type);
19 | routeValueDictionary.ProcessAction(action);
20 | routeValueDictionary.ProcessParameters(action);
21 | }
22 |
23 | public static void ProcessArea(this RouteValueDictionary routeValues, Type targetControllerType)
24 | {
25 | string areaName = targetControllerType.GetAreaName();
26 | routeValues.AddOrUpdateRouteValue("area", areaName);
27 | }
28 |
29 | public static void ProcessController(this RouteValueDictionary routeValues, Type targetControllerType)
30 | {
31 | string controllerName = targetControllerType.GetControllerName();
32 | routeValues.AddOrUpdateRouteValue("Controller", controllerName);
33 | }
34 |
35 | public static void ProcessAction(this RouteValueDictionary routeValues, LambdaExpression action)
36 | {
37 | string actionName = action.GetActionName();
38 | routeValues.AddOrUpdateRouteValue("Action", actionName);
39 | }
40 |
41 | public static void ProcessParameters(this RouteValueDictionary routeValues, LambdaExpression action)
42 | {
43 | var methodCallExpression = action.Body as MethodCallExpression;
44 | if (methodCallExpression?.Object == null)
45 | {
46 | throw new ArgumentOutOfRangeException(
47 | nameof(action),
48 | "Expected instance method call expression but received other type of expression instead.");
49 | }
50 |
51 | var methodParameters = methodCallExpression.Method.GetParameters();
52 | for (int i = 0; i < methodParameters.Length; i++)
53 | {
54 | var argumentValue = ExpressionHelpers.GetArgumentValue(methodCallExpression.Arguments[i]);
55 |
56 | routeValues.AddOrUpdateRouteValue(methodParameters[i].Name, argumentValue);
57 | }
58 | }
59 |
60 | public static void AddOrUpdateRouteValue(this RouteValueDictionary routeValues, string key, object value)
61 | {
62 | if (value == null)
63 | {
64 | return;
65 | }
66 |
67 | if (routeValues.ContainsKey(key))
68 | {
69 | routeValues[key] = value;
70 | }
71 | else
72 | {
73 | routeValues.Add(key, value);
74 | }
75 | }
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/System.Web.Mvc.Expressions/ModelStateDictionaryExtensions.cs:
--------------------------------------------------------------------------------
1 | namespace System.Web.Mvc.Expressions
2 | {
3 | using System.Linq.Expressions;
4 | using System.Web.Mvc.Expressions.Internals;
5 |
6 | public static class ModelStateDictionaryExtensions
7 | {
8 | public static void AddModelError(
9 | this ModelStateDictionary modelStateDictionary,
10 | Expression> keyExpression,
11 | string errorMessage)
12 | {
13 | ExpressionHelpers.ValidatePropertyOrIndexerExpression(keyExpression);
14 |
15 | var key = ExpressionHelpers.GetExpressionText(keyExpression);
16 | var modelState = GetModelStateForKey(modelStateDictionary, key);
17 | modelState.Errors.Add(errorMessage);
18 | }
19 |
20 | public static void AddModelError(
21 | this ModelStateDictionary modelStateDictionary,
22 | Expression> keyExpression,
23 | Exception exception)
24 | {
25 | ExpressionHelpers.ValidatePropertyOrIndexerExpression(keyExpression);
26 |
27 | var key = ExpressionHelpers.GetExpressionText(keyExpression);
28 | var modelState = GetModelStateForKey(modelStateDictionary, key);
29 | modelState.Errors.Add(exception);
30 | }
31 |
32 | private static ModelState GetModelStateForKey(ModelStateDictionary modelStateDictionary, string key)
33 | {
34 | ModelState modelState;
35 | if (!modelStateDictionary.TryGetValue(key, out modelState))
36 | {
37 | modelState = new ModelState();
38 | modelStateDictionary[key] = modelState;
39 | }
40 |
41 | return modelState;
42 | }
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/System.Web.Mvc.Expressions/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 |
3 | [assembly: AssemblyTitle("System.Web.Mvc.Expressions")]
4 | [assembly: AssemblyProduct("System.Web.Mvc.Expressions")]
5 |
--------------------------------------------------------------------------------
/System.Web.Mvc.Expressions/System.Web.Mvc.Expressions.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {B7CF5FFF-4F16-4FC4-8F5C-871CA14FC473}
8 | Library
9 | Properties
10 | System.Web.Mvc.Expressions
11 | System.Web.Mvc.Expressions
12 | v4.5
13 | 512
14 |
15 |
16 | true
17 | full
18 | false
19 | bin\Debug\
20 | DEBUG;TRACE
21 | prompt
22 | 4
23 | System.Web.Mvc.Expressions.ruleset
24 |
25 |
26 | pdbonly
27 | true
28 | bin\Release\
29 | TRACE
30 | prompt
31 | 4
32 | System.Web.Mvc.Expressions.ruleset
33 |
34 |
35 |
36 | True
37 | ..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll
38 |
39 |
40 |
41 |
42 |
43 | ..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.Helpers.dll
44 | True
45 |
46 |
47 | ..\packages\Microsoft.AspNet.Mvc.5.2.3\lib\net45\System.Web.Mvc.dll
48 | True
49 |
50 |
51 | ..\packages\Microsoft.AspNet.Razor.3.2.3\lib\net45\System.Web.Razor.dll
52 | True
53 |
54 |
55 |
56 |
57 |
58 |
59 | ..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.WebPages.dll
60 | True
61 |
62 |
63 | ..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.WebPages.Deployment.dll
64 | True
65 |
66 |
67 | ..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.WebPages.Razor.dll
68 | True
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
100 |
--------------------------------------------------------------------------------
/System.Web.Mvc.Expressions/System.Web.Mvc.Expressions.ruleset:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
--------------------------------------------------------------------------------
/System.Web.Mvc.Expressions/UrlHelperExtensions.cs:
--------------------------------------------------------------------------------
1 | namespace System.Web.Mvc.Expressions
2 | {
3 | using System;
4 | using System.Linq.Expressions;
5 | using System.Threading.Tasks;
6 | using System.Web.Mvc;
7 | using System.Web.Mvc.Expressions.Internals;
8 |
9 | public static class UrlHelperExtensions
10 | {
11 | public static string Action(
12 | this UrlHelper url,
13 | Expression> action,
14 | object routeValues = null)
15 | where TController : Controller
16 | {
17 | var routeInfo = RouteInformation.FromExpression(action, routeValues);
18 | return url.Action(routeInfo.ActionName, routeInfo.ControllerName, routeInfo.RouteValueDictionary);
19 | }
20 |
21 | public static string Action(
22 | this UrlHelper url,
23 | Expression> action,
24 | object routeValues = null)
25 | where TController : Controller
26 | {
27 | var routeInfo = RouteInformation.FromExpression(action, routeValues);
28 | return url.Action(routeInfo.ActionName, routeInfo.ControllerName, routeInfo.RouteValueDictionary);
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/System.Web.Mvc.Expressions/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ivaylokenov/ASP.NET-MVC-Lambda-Expression-Helpers/a14a62f5b673454596fb4b9df697b122823deee6/logo.png
--------------------------------------------------------------------------------
/nuget-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ivaylokenov/ASP.NET-MVC-Lambda-Expression-Helpers/a14a62f5b673454596fb4b9df697b122823deee6/nuget-logo.png
--------------------------------------------------------------------------------