Asp.net mvc Html.Action render at wrong position - asp.net

the code is
<div class="container" >
#Html.Action("aaa","bbb");
</div>
the action output string "123",
What I want is
<div class="container" >
123
</div>
but actually the result is
123
<div class="container" >
</div>
the action result place in wrong position ,why and how resolve ,Thanks in advance
action code below
public ActionResult Test(string custEmpId)
{
model.code = "123";
return PartialView(model);
}

Related

ASP.Net Core MVC - Validation Summary not working with bootstrap tabs and dynamically loaded content

How do you get dynamically loaded tabs to work in ASP.Net Core MVC?
I have a simple Index.cshtml that uses bootstrap tabs to create two tabs from the a tags on the page. (To test out options, I first copied from https://qawithexperts.com/article/asp.net/bootstrap-tabs-with-dynamic-content-loading-in-aspnet-mvc/176)
There is a click event on each tab that uses $.ajax() to call the controller and then set the html of the appropriate div.
I have a model with one field, a string that is required.
I have the create view that Visual Studio created.
When I run it and click the first tab, the controller returns PartialView("FirstTabCreate") and loads into the div and everything looks great.
The problem is when clicking the "Create" button.
The controller method checks if IsValid on the ModelState. If not, here is where I run into a problem. If I return the partial view and the model that was passed in I see my validation errors as expected but because I returned the partial view, I lose my tabs. If I return the main view (Index) then the javascript reloads my partial view and has lost the ModelState at that point.
I am not sure what to return so that this works. I have seen lots of examples online that use dynamically loaded tabs but none of them have models or validation.
Code below:
Index Page
#model FirstTab
<!-- Tab Buttons -->
<ul id="tabstrip" class="nav nav-tabs" role="tablist">
<li class="active">
Submission
</li>
<li>
Search
</li>
</ul>
<!-- Tab Content Containers -->
<div class="tab-content">
<div class="tab-pane active" id="FirstTab">
</div>
<div class="tab-pane fade" id="SecondTab">
</div>
</div>
<script src="~/lib/jquery/dist/jquery.min.js"></script>
<script>
$('#tabstrip a').click(function (e) {
e.preventDefault();
var tabID = $(this).attr("href").substr(1);
$(".tab-pane").each(function () {
console.log("clearing " + $(this).attr("id") + " tab");
$(this).empty();
});
$.ajax({
url: "/#ViewContext.RouteData.Values["controller"]/" + tabID,
cache: false,
type: "get",
dataType: "html",
success: function (result) {
$("#" + tabID).html(result);
}
});
$(this).tab('show');
});
$(document).ready(function () {
$('#tabstrip a')[0].click();
});
</script>
FirstTabCreate View
#model WebApplication1.Models.FirstTab
<h4>FirstTab</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form asp-action="FirstTabCreate">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="FirstName" class="control-label"></label>
<input asp-for="FirstName" class="form-control" />
<span asp-validation-for="FirstName" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</form>
</div>
</div>
<div>
<a asp-action="Index">Back to List</a>
</div>
Model
using System.ComponentModel.DataAnnotations;
namespace WebApplication1.Models
{
public class FirstTab
{
[Required()]
public string FirstName { get; set; }
}
}
Controller
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using System.Diagnostics;
using WebApplication1.Models;
namespace WebApplication1.Controllers
{
public class HomeController : Controller
{
public IActionResult Index()
{
return View();
}
public ActionResult FirstTab()
{
return PartialView("FirstTabCreate");
}
public ActionResult FirstTabCreate(FirstTab model)
{
if (!ModelState.IsValid)
{
return View("FirstTabCreate", model);
}
return Content("Success");
}
public ActionResult SecondTab()
{
return PartialView("_SecondTab");
}
}
}
I don't like it but to get it to work, when I click Save, in the Controller method I check if the ModelState is valid. If not, I put the keys and values into a list of custom class and then put that list in the cache. When the child partial view loads it checks to see if there is anything in the cache and if so, parses it back out and uses ModelState.AddModelError().
It's not pretty but it does allow the validation to work.
try to add jquery validation scripts in your code
delete this
<script src="~/lib/jquery/dist/jquery.min.js"></script>
and use this instead
#section Scripts {
#{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
Add below code to your #section Scripts
#section Scripts {
#{await Html.RenderPartialAsync("_ValidationScriptsPartial"); }
<script>
$.validator.setDefaults({
ignore: []
});
</script>
}
Note: do not add the above inside $(document).ready()

How can I change the attribute in header section of cshtml files?

I have a problem about removing attributes when I navigate pages.
I used PartialView in HomeController to define index.cshtml page.
The line which I pass the data to the destination is showed orderly.
HomeController -> Contract.cshtml -> _Layout.cshtml -> NavbarPartial.cshtml
Here is HomeController.cs file shown below.
public ActionResult ContractUs()
{
ViewBag.Attribute = ""; // header-transparent
return View();
}
Here is my Contract.cshtml shown below.
#{
ViewBag.Title = "Contract Us";
Layout = "~/Views/Shared/_Layout.cshtml";
}
Here is my _Layout.cshtml shown below.
Html.RenderAction("NavbarPartial", "Home");
Here is my NavbarPartial.cshtml shown below.
<header id="header" class="fixed-top d-flex align-items-center header-transparent">
</header>
What I want to do is to show this header code snippet in the index page and show another one on another page like this shown as below without changing NavbarPartial.cshtml.
Index.cshtml
<header id="header" class="fixed-top d-flex align-items-center header-transparent">
</header>
Contract.cshtml
<header id="header" class="fixed-top d-flex align-items-center">
</header>
How can I do that?
If you render your partial view from another view, then you can send some parameters to decide what class should be applied. So let's look at the example.
We call partial view and send additional data:
#{Html.RenderPartial("_Header", new ViewDataDictionary { { "ApplyStyle", true } });}
and then in partial view we can apply style conditionally:
#{
var yourClasses = "";
if ((bool)ViewData["ApplyStyle"])
{
yourClasses = "fixed-top d-flex align-items-center header-transparent";
}
else
{
yourClasses = "fixed-top d-flex align-items-center";
}
}
<header id="header" class="#yourClasses">
This is header!
</header>
UPDATE:
This is a fiddle with complete example. However, this fiddle does not support PartialView, but I believe basic idea is shown.
Try using conditions in class value.
For example:
<header id="header" class="fixed-top d-flex align-items-center #(#Model.name === 'index' ? 'header-transparent' : '')">
If you dont have any kind of variable name for current component, you can use Javascript's location object.
window.location.pathname will provide you the pathname of current page.
Using this value you can add conditional class values

Illegal characters in path in Html.RenderAction

I am trying to call child action from view as below
#{
Html.RenderAction("Render", "ProgressBar", new { total = 10, completed = 3 });
};
and my controller code is as below
public class ProgressBarController : Controller
{
// GET: ProgressBar
[ChildActionOnly]
public ActionResult Render(int total, int completed)
{
ViewBag.Total = total;
ViewBag.Completed = completed;
ViewBag.Percent = ((completed * 100) / total).ToString("0.#####");
return PartialView();
}
}
and partial view for Render
<div class="section-progress-wrapper">
<div class="section-progress-info clearfix">
<div class="section-progress-label float-l">
<span class="section-progress-output">#ViewBag.Completed</span>
<span class="section-progress-desc">of</span>
<span class="section-progress-total">#ViewBag.Total</span> modules completed
</div>
<div class="section-progress-icon float-r"></div>
</div>
<div class="section-progress-box">
<div id="progressBar" class="section-progress-range" style="width:#string.Format("{0}%",ViewBag.Percent)"></div>
</div>
</div>
but for some reason I am getting exception saying
System.ArgumentException: Illegal characters in path.
I am not able to figure out what I am doing wrong. Can someone please help?

How to make your views DRY with MVC5 and multiple page breakpoints?

I have a predicament that I am not quite sure how to overcome. I do not know what is the right way. I am building a website and I was given a template to integrate with my server code. The problem lies in how the template is outlined. Let me show you an example.
<body>
<div class="breakpoint active" id="bp_infinity" data-min-width="588">
<div id="header">full page header content</div>
<div id="body">some stuff</div>
<div id="footer">some stuff</div>
</div>
<div class="breakpoint" id="bp_587" data-min-width="493" data-max-width="587">
<div id="header">mobile header content</div>
<div id="body">some stuff</div>
<div id="footer">some stuff</div>
</div>
<div class="breakpoint" id="bp_492" data-max-width="492">
<div id="header">mobile header content</div>
<div id="body">some stuff</div>
<div id="footer">some stuff</div>
</div>
</body>
I am trying to setup my MVC5 Views in a way that does not repeats common code. The problem that I am facing is that the header and footer div are common code from page to page and the body changes. The second problem is that each page has different number of breakpoints. Here is a second page to show what I mean:
<body>
<div class="breakpoint active" id="bp_infinity" data-min-width="588">
<div id="header">full page header content</div>
<div id="body">some stuff</div>
<div id="footer">some stuff</div>
</div>
<div class="breakpoint" id="bp_587" data-max-width="587">
<div id="header">mobile header content</div>
<div id="body">some stuff</div>
<div id="footer">some stuff</div>
</div>
</body>
So the Layout page is now tricky to setup because I can't just say:
<body>
#RenderBody
</body>
One of the solutions I thought of was to use Sections, something like this:
<body>
#RenderBody
#RenderSection("Breakpoint-1", false)
#RenderSection("Breakpoint-2", false)
#RenderSection("Breakpoint-3", false)
</body>
Now each page would be along the lines of:
#section Breakpoint-1
{
<div class="breakpoint active" id="bp_infinity" data-min-width="588">
#{ Html.RenderPartial("full-page-header"); }
#{ Html.RenderPartial("full-page-body"); }
#{ Html.RenderPartial("full-page-footer"); }
</div>
}
#section Breakpoint-2
{
<div class="breakpoint" id="bp_587" data-max-width="587">
#{ Html.RenderPartial("mobile-page-header"); }
#{ Html.RenderPartial("mobile-page-body"); }
#{ Html.RenderPartial("mobile-page-footer"); }
</div>
}
A problem that I see with above code is that if the header now needs to have 5 breakpoints instead of 2, I need to go and modify it everywhere.
Is there a better way to do this? Is what I thought of the best solution for my scenario?
EDIT: To clarify. There are multiple brakpoints in the HTML because only one of them is active at a time. When page hits a certain width, 1 the currenct active breakpoint gets hidden and the new one becomes visible.
Assumptions
... are the mother of all....
"some stuff" that goes in the body tag is HTML being fed from some data source, or is hard-coded
"...the header and footer div are common code from page to page..." means that literally, you don't need to change the header/footer at all. (You still could, but I'm ignoring that for now)
The div id's "header", "body", "footer" should be handled as dom classes rather than dom ids. That is another discussion, but ids should always be unique.
Solution
This is a basic example, there are plenty of other approaches to try and plenty of other tweaks you can make
Controller
Let's call this BreakpointController
public ActionResult Index()
{
var model = new List<BreakpointViewModel>();
// populate model
return View(model);
}
ViewModel
public class BreakpointViewModel
{
public string BreakPointId { get; set; }
public int? MinWidth { get; set; }
public int? MaxWidth { get; set; }
public string Body { get; set; }
public bool IsActive { get; set; }
}
View
This should be your index.cshtml (or whatever you want to call it)
#model IEnumerable<WebApplication1.Models.BreakpointViewModel>
<div>
<h1>A header!</h1>
</div>
#Html.DisplayForModel()
<div>
<h4>A footer!</h4>
</div>
DisplayTemplate
* Thou shalt live in the folder containing views for the controller (or Shared)
* Thou shalt live in a subfolder named 'DisplayTemplates'
* Thou shalt be named {ModelName}.cshtml
in the end, the folder structure should look something like this:
Views
|-- Breakpoint
| |-- DisplayTemplates
| | +-- BreakpointViewModel.cshtml
| +-- Index.cshtml
And BreakpointViewModel.cshtml should look like this:
#model WebApplication1.Models.BreakpointViewModel
<div class="breakpoint #(Model.IsActive ? "active" : null)"
id="#Model.BreakPointId"
#(Model.MinWidth.HasValue ? "data-min-width='" + Model.MinWidth + "'" : null)
#(Model.MaxWidth.HasValue ? "data-max-width='" + Model.MaxWidth + "'" : null)>
#Html.Raw(Model.Body)
</div>
Note the minwidth/maxwidth lines in the div. Not required, just how I would personally deal with the widths.
Resulting HTML
<div>
<h1>A header!</h1>
</div>
<div class="breakpoint active"
id="bp_1"
data-max-width='720'>
<div>Hello World!</div>
</div>
<div class="breakpoint"
id="bp_2"
data-max-width='720'>
<div>Another Breakpoint</div>
</div>
<div class="breakpoint"
id="bp_3"
data-max-width='720'>
<div>Third Breakpoint</div>
</div>
<div class="breakpoint"
id="bp_4"
data-max-width='720'>
<div>Fourth Breakpoint</div>
</div>
<div>
<h4>A footer!</h4>
</div>
Original Answer
DisplayTemplates are your friend. If your sections are going to be the same, you can put the relevant information into a ViewModel, then pass the List<ViewModel> to the DisplayTemplate. The MVC engine will then use the DisplayTemplate for your ViewModel to fill out the needed code for each section.
You only need code your DisplayTemplate for your ViewModel once.
I don't have any sample code up at the moment, but if you need further help, comment on this and I'll break some out over the weekend.

Cant get the image to show in Umbraco7 with razor

I have used the media picker as data type for the type, for which the user is going to choose what image they want as the deal image.
But for some reason i can't get the razor syntax to show the image. If I make an If statement to check if the page contains an image then it won't. I think this is a problem that occurs because i have misunderstood something.
My current razor statement:
<img src="#Umbraco.TypedMedia(Model.Content.GetPropertyValue("deal1image")).Url" />
The above code won't show anything.
Hope any of you can guide me to what i do wrong and evt. stuff I'm missing.
This is how my current home.cshtml looks like:
#inherits Umbraco.Web.Mvc.UmbracoTemplatePage
#{
Layout = "Master.cshtml";
}
<div class="container">
<div class="col-md-4">
<!--Image here-->
<img src="#Umbraco.Media(CurrentPage.deal1image).Url" />
<div class="thumbnail thumbnailcustom thumbnailbg1">
<h3>#Umbraco.Field("dealtitle1")</h3>
<p>#Umbraco.Field("dealdescription1")</p>
</div>
</div>
<div class="col-md-4">
<!--Image here-->
<div class="thumbnail thumbnailcustom thumbnailbg2">
<h3>#Umbraco.Field("dealtitle2")</h3>
<p>#Umbraco.Field("dealdescription2")</p>
</div>
</div>
<div class="col-md-4">
<!--Image here-->
<div class="thumbnail thumbnailcustom thumbnailbg3">
<h3>#Umbraco.Field("dealtitle3")</h3>
<p>#Umbraco.Field("dealdescription3")</p>
</div>
</div>
</div>
You need to use Umbraco.Media to get the media. So like this
<img src="#Umbraco.Media(Model.Content.GetPropertyValue("deal1image").ToString()).Url" />
Or
<img src="#Umbraco.Media(CurrentPage.deal1image).Url" />
An example of using Umbraco.Media:
var myPage = CurrentPage.AncestorsOrSelf().Where("DocumentTypeAlias == #0", "yourPageAlias").First();
Umbraco.Media(myPage.myImage.ToString()).Url
Link on OUR Umbraco offers two solutions:
Typed:
#if (Model.Content.HasValue("caseStudyImages"))
{
var caseStudyImagesList = Model.Content.GetPropertyValue<string>("caseStudyImages").Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries).Select(int.Parse);
var caseStudyImagesCollection = Umbraco.TypedMedia(caseStudyImagesList).Where(x => x != null);
foreach (var caseStudyImage in caseStudyImagesCollection)
{
<img src="#caseStudyImage.Url" style="width:300px;height:300px" />
}
}
Dynamic:
#if (CurrentPage.HasValue("caseStudyImages"))
{
var caseStudyImagesList = CurrentPage.CaseStudyImages.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries);
var caseStudyImagesCollection = Umbraco.Media(caseStudyImagesList);
foreach (var caseStudyImage in caseStudyImagesCollection)
{
<img src="#caseStudyImage.Url" style="width:300px;height:300px" />
}
}
Also, double check your media picker data type alias. Typos are rather common in this part.
This may be a bit clunky compared to other answers but this is what I currently have.
var imageId = Model.Content.GetPropertyValue<int>("eventPoster"); // gets node id
var evId = evpId.Id; // gets image id
var evMd = Umbraco.Media(evId); // I believe this turns the id into a string
var evUrl = evMd.Url; // gets the url of the string

Resources