Viewmodel in partial and duplicates - razor

I have really strange problem. So, my structure is like this
<div id="tasks">
#Html.Partial("_Tasks", tasks)
</div>
and in _Tasks I do a foreach through all tasks and for each task I have additional partial
...
#Html.Partial("_Time", new TimeViewModel(task))
...
and inside of _Time I have form
...
#Html.TextBoxFor(m => m.Name)
....
So in a view I render a partial and then inside again multiple partials and inside it a form. When I perform a page load, it works. Problem begins with when I'm using ajax, so I perform edit to Time and post to server and update #tasks with returned html.
I'm my controller action I have...
...
return View("_Tasks", tasks);
and the problem now is that all inputs generated by #Html.TextBoxFor(m => m.Name) have the same value. Why? If I do
#Html.DisplayFor(m => m.Name)
I works just fine. I also tried with
#Html.TextBoxFor(m => m.Name, new { Value = Model.Name })
and it works, but it looks hackish to me.
The question is, why is get this behavior? Why does all TextBoxFor have same value?

Default model binder in ASP.NET MVC determines how to map the values to your model by using name attributes on input tags. All the html helpers generate markup with that in mind.
So when you write
#Html.TextBoxFor(m => m.Name)
It generates something like this:
<input type="text" name="Name" />
However when you use this helper in a partial view and try to bind a model that's a property of the main model, it won't work. Html helper in the partial will still generate markup thinking its model is the main model. So your input will be binded to main model's Name property. You can take a look a this question for solving this problem. Also keep in mind the default binder can not pick up complex collections when you handle post requests.

Related

How to properly concatenate multiple variables in asp.net core ViewData[] object of a view

Up at top of my view:
#{
ViewData["Title"] = #Html.DisplayFor(model => model.SETitle);
ViewData["Description"] = #Html.DisplayFor(model => model.SEDescription);
ViewData["canonical"] = String.Concat("https://example.com/", Html.DisplayFor(model => model.CategoryURL), "/", Html.DisplayFor(model => model.URLSlug));
}
This renders in the browser like so:
<link rel="canonical" href="https://example.com/Microsoft.AspNetCore.Mvc.ViewFeatures.StringHtmlContent/Microsoft.AspNetCore.Mvc.ViewFeatures.StringHtmlContent">
I am using a standard asp.net core template. And it seems like this will always occur if you are concatenating multiple variables together for a ViewData[] string. What do I need to change about my syntax to get this actual values to pass through and render in my browser?
All your properties appear to be type of string so there is no need to use Html.DisplayFor() (but if you do, then it needs to be #Html.DisplayFor() - note the leading # so the result of the method is output).
Instead you can just use #Model.CategoryURL and #Model.URLSlug.
And if https://example.com/ is your site, then you should be doing this using the Url.Action() method to generate the correct relative url without hard-coding the site name.
In addition, you have commented that these values are being used in your layout, in which case, consider using base view model containing those properties and set them in the controller method so that the Layout uses #model yourBaseViewModel, and each view that uses that layout inherits from your base view model

(m => m.Email) meaning (ASP.NET) and how to get a user's username

I am brand new to web development. What little experience I have is in C# Unity and Java. The code below was taken from the screen followed by the Google authentication/login screen. I am trying to set the user's Google name to the username on the website. I was wondering if someone could help me out and maybe explain what (m => m.Email) means.
Thank you so much!
#model Start.Models.ExternalLoginConfirmationViewModel
#using (Html.BeginForm("ExternalLoginConfirmation", "Account", new { ReturnUrl = ViewBag.ReturnUrl }, FormMethod.Post, new { #class = "form-horizontal", role = "form" })) {
#Html.AntiForgeryToken()
<hr />
<div class="form-group">
<div class="col-md-10">
#Html.TextBoxFor(m => m.Email)
</div>
</div>
<input type="submit" />
}
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
in the code #Html.TextBoxFor(m => m.Email) the variable m represents the current model, which is set at the top of the file as Start.Models.ExternalLoginConfirmationViewModel.
m => m.Email means "get the Email property from this model". If you were to look at the model (in Visual Studio put your mouse cursor on ExternalLoginConfirmationViewModel and press F12) you will most likely see that there is an Email property on it.
So #Html.TextBoxFor(m => m.Email) creates the HTML needed to show a textbox for the email address of the current model.
In the end it will probably generate some HTML that looks like this:
<input type="text" value="bob#example.com" id="some-generated-id-here" />
This is using the MVC Razor syntax, which you might want to do some reading up on.
https://learn.microsoft.com/en-us/aspnet/web-pages/overview/getting-started/introducing-razor-syntax-c
https://learn.microsoft.com/en-us/aspnet/core/mvc/views/razor
http://www.tutorialsteacher.com/mvc/razor-syntax
Here's the slightly more technical explanation. The => operator denotes a lambda, which can be thought of as a function that returns its value in place. The stuff on the left side (m) is the parameter(s) to the "function", and the stuff on the right side is what will be returned from the "function". Given that, m => m.Email means, essentially, "return the Email property of what I pass in here".
However, when it comes to things like HtmlHelpers, what you're passing as the first parameter there is actually Expression<Func<TModel, TProperty>>, so let's unwrap that. Func<TModel, TProperty> is the actual type of that lambda we just talked about. Func is a generic type, with two (or more) type parameters. Here, the first type parameter is TModel, and corresponds to the type of the "left side" of the lamda, i.e. the type of the thing we're passing in. The TProperty type parameter is the type of the "right side" of the lambda, i.e. the thing we're returning.
Expression is a wrapper applied to things like Func, and builds what's called an "expression tree" out of the lambda. This expression tree, among other things, allows the inspection of what's inside that lambda, so you can determine things like the name of the property that's being returned. The HtmlHelpers, then, use this information to do things like generating id and name attributes, which obviously need to match the property name. This is actually an important thing to recognize as a lot of new developers get confused and think they can pass in just about anything to an HtmlHelper as the expression. That's not the case, because you're not dealing with a value, but rather an expression representing a value. For example, the following would not work at all:
#Html.TextBoxFor(m => m.Email.ToLower())
Because it's not a valid expression, even though it works for the purpose of the lambda.

rails custom html elements form

I am new in Rails and i've searched around the web and books but I couldnt find how to make custom forms when working with rails..
what happens is that I am used to write my own HTML tags and I confortable with that. I dont like to use libs like JSF (from JAVA) that writes html components for me and I dont want that rails write it for me, except for simple tags like
text_field(:post, :title, :size => 20)
# => <input type="text" id="post_title" name="post[title]" size="20" value="#{#post.title}" />
so.. how can I do that.. for example: I would like to write by myself
<input type="text" class="myclass" data="mydata" name="how-to-get-the-attribute-name-with-rails" value="how-to-get-value-with-rails" />
how can I do that?
If you want more control over the html you are creating, you can also use a content_tag
content_tag :input, "label_name", class: "myclass", data: "mydata", name: "how-to-get-the-attribute-name-with-rails", value: "how-to-get-value-with-rails"
You can supplement any html element tag for :input. So if you want a div instead, use :div etc...
As you have written above, The name of any form field in rails is in the following format
name = 'post[name]' i.e. model_name[attribute_name]
So your params hash will contain :post => {:name => value} which allows you to use mass-assignment. But if you want to get some extra parameters from the form you can directly include them in the form and give them any name as you want. It will be available in your params hash.
You can get value easily using value = <%= #object.attribute_name. %>
I am not sure if you wanted to know this or something else. Let me know if you need more help.
You can simply write html inside a Rails form, so
<input type="text" class="myclass" data="mydata" name="how-to-get-the-attribute-name-with-rails" value="how-to-get-value-with-rails" />
is perfectly valid, but note that you should use the names and id's in correct way to automatically bind them to your back end controller.
After all, what text_field(:post, :title, :size => 20) does is it convert the parameters to pure HTML (we call them helper methods in Rails).
Read here for formhelper options (using helpers will keep your code clean).

MVC3 how to get innerHtml from the return sting of #Html.ValidationMessageFor<> method?

I want to show the validation message summary in the tool tip of an html box. Something like this,
#Html.TextBoxFor(m => m.Contract.PrimaryContact.FirstName, new { #class = "quarter", title = #Html.ValidationMessageFor(m => m.Contract.PrimaryContact.FirstName) })
How can I do it? As of now am seeing the entire html mark up of the validation message in the title. Is there a way I can just see the validation message?
Thanks!
I'm afraid the only proper way is to reimplement the Validation helper methods. Fortunately it isn't hard and the source is available online.

MVC3 - razor : How to use mailto dynamically

I have a link as bellow. Is there any way to change info#example.co.uk with model.Contact.EmailAddress to make it dynamics.
#Html.LabelFor(model => model.Contact.EmailAddress)</dd>
If the Contact is a property of your model which is binded to your view, you can use it like this
#Model.Contact.EmailAddress
If it is a child property of your model and you want to do it inside a loop, you can do like this
#foreach (var item in Model.Contacts)
{
#item.Contact.EmailAddress
}
Simply use the appropriate razor syntax inline with your html as you would normally do when writing any output from your model.
#Html.LabelFor(model => model.Contact.EmailAddress)