Implementing Forms in ASP.net MVC - c#

I have a simple form on a view page, implemented as a user control, that looks something like this:
<%=Html.BeginForm("List", "Building", FormMethod.Post) %>
//several fields go here
<%Html.EndForm(); %>
There are two problems I would like resolved, the first is that I would like the controller method that receives this to take a type parameter of the user control. The goal is to avoid putting all of the fields of the form into the parameter list for the method. The controller method currently looks like this:
[AcceptVerbs("Post")]
public ActionResult List(string capacityAmount)
{
ProfilerDataDataContext context = new ProfilerDataDataContext();
IEnumerable<Building> result = context.Buildings.OrderBy(p => p.SchoolName);
ViewData["Boroughs"] = new SelectList(Boroughs.BoroughsDropDown());
return View(result);
}
The rest of the fields in the form will be used to conduct a search against the buildings type.
The form posts fine, I can search on the capacity the way you would expect, but I can smell ugliness ahead as I add parameters to the search.
Second, smaller problem is that when the page renders the BeginForm tag renders the string "System.Web.Mvc.Form" to the page. How do I make that go away?

1) Use FormCollection as the argument:
public ActionResult List(FormCollection searchQuery)
Now you can iterate the FormCollection and get key/value search terms from your search form.
2) Remove the "=" from BeginForm:
<% Html.BeginForm("List", "Building", FormMethod.Post) %>
That said, you should really be using, um... using:
<% using (Html.BeginForm("List", "Building", FormMethod.Post)) { %>
<% } %>

If I'm understanding your question properly, you use the html helper and create inputs named:
<%=Html.TextBox("building.FieldNumber1")%>
<%=Html.TextBox("building.FieldNumber2")%>
You should be able to access the data using:
public ActionResult List(Building building)
{
...
var1 = building.FieldNumber1;
var2 = building.FieldNumber2;
...
}
and if your action is to do two different things depending on if form is submitted:
public ActionResult List()
{
//some code here
}
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult List(Building building)
{
...
var1 = building.FieldNumber1;
var2 = building.FieldNumber2;
...
}

if anybody is skeptical about the whole 'using' pattern with Html.BeginForm - realize that the IDE is smart enough to match the opening '{' with the ending '}' which makes it very easy to see where your form begins and ends.
Also <% Html.EndForm(); %> requires a semicolon which I'm not sure i like :)

Related

Display Each Element From Array Using HTML Helper in C#

This is probably a very simple problem, but I am extremely new to C# / MVC and I have been handed a broken project to fix. So it's time to sink or swim!
I have an array of strings that is being passed from a function to the front end.
The array looks something like
reports = Directory.GetFiles(#"~\Reports\");
On the front end, I would like it to display each report, but I am not sure how to do that.
This project is using a MVC, and I believe the view is called "Razor View"? I know that it's using an HTML helper.
In essence, I need something like
#HTML.DisplayTextFor(Model.report [And then print every report in the array]);
I hope that makes sense.
If you want to display the file name array you can simply use a foreach:
#foreach(var report in Model.Reports){ #report }
Note that you should add the Reports property to your view model:
public class SampleViewModel
{
public string [] Reports { get; set; }
}
You could use ViewData or TempData but I find that using the view model is the better way.
You can then populate it:
[HttpGet]
public ActionResult Index()
{
var model = new SampleViewModel(){ Reports = Directory.GetFiles(#"~\Reports\")};
return View(model);
}
And use it in the view as you see fit.
Here is a simple online example: https://dotnetfiddle.net/5WmX5M
If you'd like to add a null check at the view level you can:
#if(Model.Reports != null)
{
foreach(var report in Model.Reports){ #report <br> }
}
else
{
<span> No files found </span>
}
https://dotnetfiddle.net/melMLW
This is never a bad idea, although in this case GetFiles will return an empty list if no files can be found, and I assume a possible IOException is being handled.

Load Partial View inside another Partial View

I have a PartialView (_Letra) that receives information from a Controller named Music ... this way
public ActionResult CarregarLetra(string id, string artista, string musica)
{
return PartialView("_Letra", ArtMus(artista, musica));
}
public ResultLetra ArtMus(string artista, string musica)
{
//Conteúdo do metodo[..]
var queryResult = client.Execute<ResultLetra>(request).Data;
return queryResult;
}
Until then, no problem. What happens is that now I need to pass other information to this same PartialView (_Letra). This information is in PartialView (_Cifra).
So I added the following lines in my Music controller
public ActionResult CarregarCifra(string id, string artista, string musica)
{
return PartialView("_Cifra", GetCifra(artista, musica));
}
public ResultChords GetCifra(string artista, string musica)
{
var cfrTest= new Cifra();
var cifra = new ResultChords();
cifra.chords = cfrTest.GetInfs(artista, musica);
return cifra;
}
Everything working so far, PartialView _Cifra receives the information
I searched and found that I could use in PartialView _Letra the Html.Partial to load my PartialView _Cifra, I did this way then
I added
<div class="item">
<div class="text-carousel carousel-content">
<div>
#Html.Partial("_Cifra", new letero.mus.Infra.Models.ResultChords());
</div>
</div>
</div>
Now it starts to complicate why, the return of this is null, I believe it is due to a new instance of ResultChords that I make in Html.Partial
I have already tried using a ViewBag also to transpose the information between Partials, but probably not correctly, due to the return being null as well.
I've already done a lot of research and I'm not getting the information I need for PartialView _Letra.
There is a better way not to use Html.Partial, or to use it properly, as I am not aware.
In _Letra use
#Html.Action("CarregarCifra", "Music", new { id=Model.Id, artista=Model.Artista, musica=Model.Musica });
if the variables are available on the model then you can pass them in; otherwise, make use of the Viewbag and set them in CarregarLetra
Are you always passing a new object to the second partial? You could just create it at the top of the new _Cifra partial.
_Cifra.cshtml
#{
var resultChords = new letero.mus.Infra.Models.ResultChords();
}

Set page count on dynamic pages & maintain page visit count in database

I just want to know the logic of this. I am not posting any code because I don't know what is the logic behind this so please pardon. I have a page call dynamicPage. This page is connected with database & everytime details of particular things gets fetched according to users selected. Now I want to track How many time particular thing is visited.
e.g.
Hospital1
Hospital2
Hospital3
If user clicks on Hospital2 then it's count get increased by one & so on..
I made this site http://www.brandstik.in/Music here many products are listed. Now I want to see how many times particular products is viewed.
You need something between clicking on the product link and loading the detail page. There are lots of ways to do that. One of the easiest ones is to have a method between you clicked on the link and loading the detail page. So the simplest solution that I can suggest is to have an action (if it is MVC) or a simple method on detail page, increase the count and then redirect to the original one. So lets say your code is in MVC and you have a method like this on dynamic page:
#Html.ActionLink("#item.productName", "Index", "Products", new {id = "#item.id"}))
and you have this code in your products controller:
public class ProductsController:Controller
{
Public ActionResult Index(int Id)
{
...some code to load and return the productDetails
}
}
Then you need to add a method to add to the count and then redirects to the original method. so your controller will be like this:
public class ProductsController:Controller
{
Public ActionResult Index(int Id)
{
//some code to load and return the productDetails
}
public ActionResult IncreaseProductCount(int Id)
{
//increase the count
return RedirectToAction("Index",new{Id=Id});
}
}
And then on the dynamic page view change your code to call the new method instead:
#Html.ActionLink("#item.productName", "IncreaseProductCount", "Products", new {id = "#item.id"}))

The controller for path '/' was not found or does not implement IController

I'm working on a piece of code that shows a random sponsor image on each webpage. I figured that the best place to call my function is in the Views/Shared/_Layout.cshtml page, because that's the one that loads at every page.
I wrote the function in a service class in my domain model, and wrote a ChildActionOnly function in my homecontroller, returns the value in a simple view in Views/Home/Randomsponsor.cshtml and called the function in the shared layout with a Html.action.
Everything builds fine, but while running i get the next error:
{"The controller for path '/' was not found or does not implement IController."}
Does anyone know how to fix this one?
Method in the domain project:
public String advertsForCountry()
{
String studentSchool = finder.getLoggedStudent().SchoolId;
int studentCountry = db.Schools.Find(studentSchool).CountryId;
List<Sponsor> sponsorsForStudent = new List<Sponsor>();
List<Advert> adverts = db.Adverts.ToList();
foreach(Advert adv in adverts)
{
foreach(Country cntry in adv.Countries)
{
if(cntry.CountryId == studentCountry)
{
sponsorsForStudent.Add(adv.Sponsor);
}
}
}
Random random = new Random();
int randomSP = random.Next(0, sponsorsForStudent.Count()-1);
string sponsorAdvert = sponsorsForStudent.ElementAt(randomSP).SponsorCompany;
return sponsorAdvert;
}
In HomeController:
[HttpGet]
[ChildActionOnly]
public ActionResult RandomSponsor()
{
var model = service.advertsForCountry();
return PartialView("RandomSponsor", model);
}
Simple view in Views/Home/ :
#{
ViewBag.Title = "RandomSponsor";
}
#Html.Action("RandomSponsor")
And my function call in the View/Shared/_Layout.cshtml whitch contains the navigation bar, etc:
#Html.Action("RandomSponsor", "HomeController")
Regards.
(Converted from comment)
You don't need to specify the full class name of the Controller in Html.Action. Try using #Html.Action("RandomSponsor", "Home") instead of #Html.Action("RandomSponsor", "HomeController").
You are missing the name of the controller. Please note, when you create a controller and called it Alexie, by default MVC will name it AlexieController. Therefore, when you are calling a function within a controller, it should be like this:
#Html.Action("Function Name", "Alexie").
And not like this:
#Html.Action("Function Name", "AlexieController").
So, I agreed with wgraham's answer.

C# MVC NerdDinner authorization helper method problem

I'm currently going through the ASP.NET MVC NerdDinner tutorial and am having a problem with a particular helper method related to user authorization. The idea is that only users who "own" a particular dinner should be able to edit or delete it (based on the Dinner object's HostedBy property).
I have the following method in my Dinner object:
public partial class Dinner {
public bool IsHostedBy(string userName) {
return HostedBy.Equals(userName, StringComparison.InvariantCultureIgnoreCase);
}
// other stuff removed for brevity
}
and in my View I'm trying to show/hide links based on whether the logged in user is the dinner's host:
<% if (Model.IsHostedBy(Context.User.Identity.Name)) { %>
<%= Html.ActionLink("Edit Dinner", "Edit", new { id = Model.DinnerID })%>
|
<%= Html.ActionLink("Delete Dinner", "Delete", new { id = Model.DinnerID })%>
<% } %>
The problem is that IsHostedBy() never returns true. I've written User.Identity.Name and Dinner.HostedBy to the screen to verify they're the same, but the method still returns false. I'm uncertain how to track down the problem.
I'm new to both C# and ASP.NET MVC, so it's very likely I'm missing something easy. Any help is appreciated and I'd be happy to post more information if it's needed.
While I'm at it I may as well write the Answer.
Check for errent spaces in the two strings.
I'm guessing that HostedBy and userName aren't actually the same string!
Some debugging ideas:
1st) Try forcing it to always return true:
public bool IsHostedBy(string userName) {
return true;
}
If this lets you return true back into the view, at least you can know that the code you're writing in the IsHostedBy method is being executed.
2nd) Add a console-out to see for yourself if the two strings are indeed equal:
public bool IsHostedBy(string userName) {
Console.WriteLine("userName: {0} / HostedBy: {1}", userName, HostedBy);
return true;
}
This will help you inspect the values of these items. Or you could just set a breakpoint at the return statement and see what they are as well.

Categories

Resources