ASP.NET MVC Editor-Templates/UIHint with parameters
Solution 1
You could use the AdditionalMetadata
attribute:
[UIHint("DateTime")]
[AdditionalMetadata("foo", "bar")]
public DateTime Date { get; set; }
and in the template:
@ViewData.ModelMetadata.AdditionalValues["foo"]
so if you wanted to pass an url:
[UIHint("DateTime")]
[AdditionalMetadata("controller", "somecontroller")]
[AdditionalMetadata("action", "someaction")]
[AdditionalMetadata("property", "someproperty")]
public DateTime Date { get; set; }
and in your template:
@{
var values = ViewData.ModelMetadata.AdditionalValues;
}
<script type="text/javascript">
$('.auto').autocomplete({
source: function (request, response) {
$.ajax({
url: '@Url.Action((string)values["action"], (string)values["controller"])',
dataType: "json",
data: {
filter: request.term
},
success: function (data) {
response(
$.map(eval(data), function (item) {
return {
label: item['@values["property"]']
}
})
);
}
});
}
});
</script>
Solution 2
You could use the UHint without AdditionalMetadata attribute, but some additional code is requred
[UIHint("DateTime", null, "key1", "value1", "key2", "value2")]
public DateTime Date { get; set; }
override CreateMetadata:
public class CustomMetadataProvider : DataAnnotationsModelMetadataProvider
{
public const string UiHintControlParameters = "UiHintControlParameters";
protected override ModelMetadata CreateMetadata(
IEnumerable<Attribute> attributes,
Type containerType,
Func<object> modelAccessor,
Type modelType,
string propertyName)
{
ModelMetadata metadata = base.CreateMetadata(
attributes,
containerType,
modelAccessor,
modelType,
propertyName);
IEnumerable<UIHintAttribute> uiHintAttributes = attributes.OfType<UIHintAttribute>();
UIHintAttribute uiHintAttribute = uiHintAttributes.FirstOrDefault(a => string.Equals(a.PresentationLayer, "MVC", StringComparison.OrdinalIgnoreCase))
?? uiHintAttributes.FirstOrDefault(a => String.IsNullOrEmpty(a.PresentationLayer));
if (uiHintAttribute != null)
{
metadata.AdditionalValues.Add(UiHintControlParameters, uiHintAttribute.ControlParameters);
}
return metadata;
}
Register CustomMetadataProvider:
public static void Application_Start()
{
ModelMetadataProviders.Current = new CustomMetadataProvider();
}
and in your template:
@{
IDictionary<string, object> values = (IDictionary<string, object>)
ViewData.ModelMetadata.AdditionalValues[CustomMetadataProvider.UiHintControlParameters];
}
Rohan Büchner
I've been writing code since the late 90s, first as a childhood hobby, then transitioning it into my career. I enjoy working in / with: JavaScript (and all of its many tails) .Net AWS (including Infrastructure as Code) Favourite IDEs: Jetbrains anything But can get by with VSCode in a pinch When I'm not programming, you'll find me on: SoundCloud: Where I post infrequently, expect random metal guitar outbursts. Eve & Ro (YouTube): This is a channel where my wife & I post travel things. Blog: Mainly tech related, but I mainly use it as a testbed to try new technologies. I have rebuilt this many times over. Currently it is NEXTJS based. ZaTech (Slack): If you need to message me for any inquiries.
Updated on June 18, 2022Comments
-
Rohan Büchner almost 2 years
I've been using Editor-Templates in the past like this, by applying the following data annotation:
[UIHint("SomeTemplate")]
ViewModel:
public class MicroViewModel { public IEnumerable<LabMicro> Micros { get; set; } [UIHint("DateTime")] public DateTime Date { get; set; } public int CaseNo { get; set; } [UIHint("SampleTypes")] public int LabSampleTypeID { get; set; } [UIHint("SampleDetails")] public int LabSampleDetailID { get; set; } }
If I wanted to use a specific date picker control as opposed to the regular one, it can be implemented as follows.
Example:
@model DateTime? @Html.TextBox("", String.Format("{0:yyyy-MM-dd}", Model.HasValue ? Model : DateTime.Today), new { @class = "dp", style="width:100px" }) <script type="text/javascript"> $(document).ready(function () { $(".dp").datepicker({ changeMonth: true, changeYear: true, dateFormat: 'yy-mm-dd' }); }); </script>
For my ID fields, I'd like to make use of the jQuery auto-complete component.
Question:
How would I go about passing additional parameters to the
UIHint
partial view forLabSampleTypeID
andLabSampleDetailID
? (As Id like to have an auto-complete Editor-Template that'll take a URL and property names for example)What I think my auto-complete Editor-Template/Partial should look like:
$(".auto").autocomplete({ source: function(request, response) { $.ajax({ url: '[#URL_TO_USE]', dataType: "json", data: { filter: request.term }, success: function(data) { response($.map(eval(data), function(item) { return { label: item.[#PROPERTY_TO_USE] } })); } }) } });
-
Anton Kalcik over 8 years
UHint
class has constructor with additionalparams object[] controlParameters
. What is the purpose of this? -
Sel over 7 years
UHint
controlParameters seems to be more sutable for this -
Ciaran Gallagher over 7 yearsHi I tried your code but on attempting to register the custom provider it says it's unable to convert target type to System.Web.Mvc.ModelMetadataProvider, any ideas?
-
Ciaran Gallagher over 7 yearsThe override that we created is extending from 'DataAnnotationsModelMetadataProvider' just like your example, but the 'ModelMetadataProviders.Current' is expecting a ModelMetadataProvider.
-
Sel over 7 yearsCiaran, enshure you override
DataAnnotationsModelMetadataProvider
fromSystem.Web.Mvc
namespace, notSystem.Web.Http.Metadata.Providers