Skip to content
This repository has been archived by the owner on Dec 19, 2018. It is now read-only.

Cannot bind a ModelExpression object directly in Razor views #926

Closed
sgjsakura opened this issue Jan 8, 2017 · 4 comments
Closed

Cannot bind a ModelExpression object directly in Razor views #926

sgjsakura opened this issue Jan 8, 2017 · 4 comments
Labels

Comments

@sgjsakura
Copy link

sgjsakura commented Jan 8, 2017

Hi all,

In my project, the project will generate a view-component view with input controls. The model expression comes from a parent view, and thus I want to pass the expresion to the inner control. The CSHTML view for the view-component just likes:

@{
  var exp = (ModelExpression)ViewBag.Exp; // the model expression object comes from the parent view with (m => m.Name)
}

<select asp-for="@exp" asp-items="..."></select>

However the generated HTML is

<select name="exp"> ... </select>

It seems that the razor generator does not correctly handle a model expression object. I may use the name attribute to set the select name directly, however, this walkaround cannot set the current selected options while get the current value manually from an expression is really complex. Could you please change the design and support the ModelExpression attribute to be set using an expression object directly?

Thank you.

@frankabbruzzese
Copy link

You cant do that. ModelExpression are inferrede from the variable definition, so with your code the select tag helper receive an expression describing the exp variable itself, instead of the ModelExpression contained in exp.

Why dont you pass the model the ModelExpression refer to in the View ViewModel?

@sgjsakura
Copy link
Author

sgjsakura commented Jan 9, 2017

@frankabbruzzese Thank you for your reply.

Actually, I'm meeting a design requirement that providing a select list which it's options' data comes from a back-end database query.

Make query in each action and passing data to the view using viewbag is lengthy and prone to error since IDE does not know how many viewbag data is need and will not mention you to provide them. While, Executing complex query in CHSTML file is also not recommended.

For my knowledge, best way to simplify the code is create a view-component to invoke the query, and render the list in its component view. However, the data binding related infomration (e.g. the name and current value of the select) is related to the parent view instead of the component itself.

The common suage for model binding is just use asp-for to provide a model expression, this way has a lot of benefits such as automatically generate the name and current-value, as well as correctly handling when model objec is not provided. Thus I think it should be the easiest way to just pass the expression into the component view.

However the Razor compilation engine cannot accept a direct model expression, thus now I have to take much more code to get the name of the select, calculate the current value, and try to avoid exceptions when model is null, and then, I also need to pass both name and value to the view compoenent and manually generate a SelectList in order to correctly set the current option. All these above steps are boring and unfriendly to code maintenance.

So if the model expression can be handled as I wished, I think it is much eaiser for some coding scenes just like what I've demostrated above.

Thank you.

@frankabbruzzese
Copy link

No No.
You can do everything without passing directly ModelExpression to select and without caring if model is null...
The main problem is getting the right names for input fields.

  1. From a conceptual point of view your ViewComponent needs jsut two stuffs the ModelExpression fullname you may get in the main View: a) prefix=ViewState.TemplateInfo.GetFullHtmlFieldId(name) where name is the name extracted from the model expression; b) the value extracted from the ModelExpression.

  2. in The ViewComponent set ViewState.TemplateInfo.HtmlPrefix = prefix (prefix computed in step a). Then return the ModelExpression value as model for the ViewComponent view,

  3. Finally in the select just put: asp-for="@model".

That's all!

@Eilon Eilon added the wontfix label Feb 1, 2017
@Eilon
Copy link
Member

Eilon commented Feb 1, 2017

Closing because we are not planning to support this behavior. The model expression feature is tied closely to the parser and code generation and there's no way for Razor to detect the difference between an expression or an object that already contains an expression.

@Eilon Eilon closed this as completed Feb 1, 2017
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

3 participants