Fill a form with ASP.NET MVC Querystring - asp.net

I want to fill a form with Id and i have made the url in this way
local-host:1613/Patient/Index/1
Where as 1 is the Id. And i want to fill my form with the data of patient with Id 1.
But this below function is not being called in Controller
public ActionResult Index(int id)
{
Patient p = new CEntities().Patients.Find(id);
return View(p);
}
instead, i am getting into
public ActionResult Index()
{
return View();
}
I am newbie in ASP.NET MVC, i have no idea in filling a form with any other way, i found a way but it shows my whole object in query string which is insecure. And this above solution is not working.
Please suggest me good solution.

As far as I know you cannot truly overload action methods in ASP.NET-MVC so there can be only one Index action method(without any additional annotations). Of course you can define few methods with the same name but then you might want to add [HttpPost](or other HTTP method) annotation above the action method to use it for instance after submitting a form.
Making parameter optional might be helpful:
public ActionResult Index(int? id){
if(id.HasValue()){
Patient p = new CEntities().Patients.Find(id);
return View(p);
}
return View();
}
Please take a look: Can you overload controller methods in ASP.NET MVC?
Another advice: try to use scaffolding and see how template does it for you:
1.Right click on a controller folder
2.Add->New Controller
3.Controller with Entity Framework read/write actions(as far as I remember 3rd from the top)
4.Select model class.
5.Select db context(class which maintains connection with database).
6.Ok.
It will generate controller with views, have fun.

local-host:1613/Patient/Index/1
This path should be hitting your action method of:
public ActionResult Index(int id)
Please check your RouteConfig.cs file and make sure you have the default route set up correctly:
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
Try commenting out your other Index action method "//public ActionResult Index()", and see what happens when trying to go to local-host:1613/Patient/Index/1

Related

How exactly does a .net MVC controller know which View() to return?

When I want to call a new page in .net, say the "About.cshtml" page, I use the following code in the HomeController:
public ActionResult About()
{
ViewBag.Title = "About";
return View();
}
To call it I'd use a link to "/Home/About". And if I wanted to create a new page called "Contact.cshtml", for example, I'd copy the above and replace About with Contact.
I know that the route in "/Home" calls the HomeController. But how, exactly, does that controller know to return the About.cshtml page? I assume it's based on the name of the function. But this doesn't sound right to me. About() isn't an HTTP verb like Get() or Post(), and the name of the function normally shouldn't define what it does, unless it already existed.
Also, when exactly is View() defined, and when is it assigned to the About.cshtml page?
Finally, is there an attribute that would allow me to return the About.cshtml page with a different function name (as I can set a function to respond to Get with the [HttpGet] attribute)?
But how, exactly, does that controller know to return the About.cshtml page?
Because the action method name is About:
public ActionResult About()
The route found that method by the URL:
/Home/About
If the URL didn't include the action:
/Home
Then it would look for a default action. Normally this is Index(), as configured by the default route mapping:
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = "" }
);
Note how a default value is defined for both controller and action if none is provided on the URL.
the name of the function normally shouldn't define what it does
Why on Earth not? A function name should exactly define what that function does.
Also, when exactly is View() defined
It's in the base controller class.
Finally, is there an attribute that would allow me to return the About.cshtml page with a different function name
Not an attribute per se, but you can specify the view name when calling View():
return View("SomeOtherView");
only to explain a few more (the David's response is so good), View() is an object of type ViewResultBase, in class Controller;
protected internal ViewResult View()
{
return View(viewName: null, masterName: null, model: null);
}
ViewResultBase has a method ExecuteResult() that receives a parameter of type ControllerContext (this parameter has the info about the request) and inside this method, if the name of the view is null, the view name is established based on the url (read the explain of David about the routing) that is called accesing to the RouteData:
public override void ExecuteResult(ControllerContext context)
{
if (context == null)
{
throw new ArgumentNullException("context");
}
if (String.IsNullOrEmpty(ViewName))
{
ViewName = context.RouteData.GetRequiredString("action");
}
....
}
Here, if you watch the RouteData you can view that the called action is Index, and this value is set to the ViewName property:
Regards,

asp.net mvc 4 custom urls for action method

I am creating a asp.net mvc 4 application
public class AspNetController : Controller
{
//
// GET: /AspNet/
public ActionResult Index()
{
return View();
}
public ActionResult Introduction()
{
return View();
}
}
as Shown Above There is AspNet Controller and Introduction Action Method
Default Url for Introduction Action Method is
localhost:55134/aspnet/introduction
But I Want Url Like
localhost:55134/aspnet/introduction-To-AspNet
Same for
/localhost:55134/aspnet/NetFrameWork To
/localhost:55134/aspnet/What-is-.Net-Framework
How to do that
You should be able to use the ActionName attribute to decorate your routes.
[ActionName("Introduction-To-AspNet")]
public ActionResult Introduction()
{
return View();
}
You really want to use AttributeRouting, either via a 3rd party package or natively if you can.
Technically this concept comes under Routing in ASP.NET MVC.
For this you need to do an entry for route in App_Start->RouteConfig.cs file under RegisterRoutes(RouteCollection routes)
For Example:
routes.MapRoute(
"customRouteName",
"aspnet/introduction-To-AspNet",
new { controller = "AspNet", action = "Introduction" });
here aspnet/introduction-To-AspNet will append after your base url i.e. localhost:55134/
The quick and dirty answer is to add a route to your ~/AppStart/RouteConfig.cs file and it will be taken care of:
routes.MapRoute(
name: "CustomRoute",
url: "Aspnet/Introduction-To-AspNet",
defaults: new { controller = "Home", action = "AspNet", id = UrlParameter.Optional }
);
However, I'm assuming this is for some type of blog? I would reccomend that you have an action method called view, and then use your name as a parameter for the article. That way, you don't have to go in and edit the code every time you add a new article or other content:
public class ArticlesController : Controller
{
public ActionResult ViewArticle(string? title)
{
ViewBag.Article = title;
return View();
}
}
that way, your URL would be www.yoursite.com/Articles/ViewArticle/Introduction-To-AspNet. In general, you don't want to add tons of specific routes to your route config if you can avoid it. That being said, if this is a legacy system, the route table may be the only way.
EDIT
Ok, so what you can do is pass the string into the ViewBag and use a case statement to determine which partial view to show (I think this just might be your ideal solution):
<!--cshtml view-->
#switch(ViewBag.Article)
{
case 'Introduction-To-AspNet':
#Html.Partial('pathToPartialView.cshtml')
break;
case 'Some-Other-Article'
#Html.Partial('pathToAnotherPartialView.cshtml')
break;
...
...
default:
#Html.Partial('invalidArticleName.cshtml')
break;
}
The controller will pass the article name through the ViewBagand then you can use the case statement to figure out which article to render... and of course, the real secret sauce you've been looking for: #Html.Partial('URL') - this will take your partial and render it right were you put that in the page. You can also pass objects to that just as an FYI.
In addition, make sure that you have a default action on the switch statement that will show some sort of 404 page that indicates that the name in the URL was invalid. You ALWAYS want to have this anytime you're taking user input from the URL because people monkey with URLs all the time (and more innocently, copy+paste them wrong/incompletely all the time)

Asp.net MVC RenderAction method in multiple controller

I am doing some plugin kind of work using asp.net mvc.
I have two plugins(mvc projects) Say users and home. In both the plugins, I have Home Controllers. Yes the names are home controller in both the plugins(projects). When I build the project the Dlls are copied to the host project (third one).
this is home plugin
namespace Plugin.Home.Controllers
{
public class HomeController : Controller
{
public string Index()
{
return "Home from home";
}
public string JustATest()
{
return "Just a test from home";
}
}
}
Here is another controller in different project(User Plugin)
this is home controller
namespace Plugin.Users.Controllers
{
public class HomeController : Controller
{
public string Index()
{
return "Home from Users";
}
public string JustATest()
{
return "Just a test from Users";
}
public string JustAnotherTest()
{
return "Just another test from Users";
}
}
}
In global.asax I have register routes using namespaces.
routes.MapRoute(
"Default", // Route name
"Home/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional },
new[] { "Plugin.Home.Controllers" }
routes.MapRoute(
"Users", // Route name
"users/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional }, new[] { "Plugin.Users.Controllers" }
);
I can access all the routes in the browser without any problem.
Now the problems
I try to use #{Html.RenderAction("JustATest","Home");}
It only renders from the home controller in home module. How can i render it from Users module.
It throws an exception saying method not found in home controller,
when I say #{Html.RenderAction("JustAnotherTest","Home");}
At what stage I can check if a given controller has the given method or not (Some ControllerFactory). Or how can i make sure it picks up the right controller.
Help will be appreciated.
Regards
Parminder
If you really need to save controller names both HomeController, i see simple solution to use hack like this:
routes.MapRoute(
null,
"{home}/{action}/{id}",
new { controller = "Home", action = "Index", home="Home", id = UrlParameter.Optional });
routes.MapRoute(
null,
"{home}/{action}/{id}",
new { controller = "Home", action = "Index", home="Users", id = UrlParameter.Optional }
);
And you can access to this actions both by url and with RenderAction:
#{Html.RenderAction("JustATest","Home", new {home="Home"});}
#{Html.RenderAction("JustATest","Home", new home="Users");}
But I think that problem is artificial (because it is more hard that you imagine), and you use means only for using means, but not for solving real problem. For real plugin architecture you need to create at least:
1. Custom Route Constraint for checking, that controller type is from assembly, where controller was defined.
2. Installer, that will install all routes independently of main application
3. Create unit tests for each plugin application Routes to ensure that all routes, that was installed from plugins, that do not know anything about each other, works properly (and don't break each other).
I recommend to take your controllers at main web application and give them different names.
See the format used here:
render action with lambda
#Html.RenderACtion<Plugin.Home.Controllers.HomeController>(...)
Edit
I see your issue now. It's that they are dynamically loaded at runtime and hence the names aren't known when you compile. Check out using DefaultControllerFactory as mentioned in various postings here:
How to achieve a dynamic controller and action method in ASP.NET MVC?

Custom route with more than one parameter in url (customer, extra info)

I have a multi tenant system and I need to allow administrators to edit the information of other customers.
I believe the correct way to do this is to append the customer ID to each request, and update my routes accordingly.
How do I make ASP.NET accept and use something like this in the controller (order doesn't mean much to me):
mysite.com/files/delete/{file}/{customerID}
and how would I pass and consume that in my controller? The ASP.NET tutorials skip this... (or I don't know where to search)
Define a route:
//mysite.com/files/delete/{file}/{customerID}
routes.MapRoute(
"Files", // Route name
"files/delete/{file}/{customerID}", // URL with parameters
new { controller = "File", action = "Delete" } // Parameter defaults
);
Create a Controller:
public class FileController : Controller
{
public ActionResult Delete(string file, string customerID)
{
//do something
return View();
}
}
I presume that {file} is a filename that should be deleted.

ASP.NET MVC route returning 404 without action

I am working on a very simple application, using MVC2 Preview 1.
I have a controller named ContentController. My problem is that /Content/Index works correctly, but /Content/ returns a 404. I am running the application on the Studio Development Server.
Tested with RouteDebugger but /Content/ returns a 404, and does not display any debugging information.
I have not changed the routing code:
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = "" } // Parameter defaults
);
This is my controller:
public class ContentController : Controller
{
IRepository _repo = new SimpleRepository("db", SimpleRepositoryOptions.RunMigrations);
public ActionResult Index()
{
var content = _repo.GetPaged<Content>(0, 20);
return View(content);
}
It's a shot in the dark, but do you have a directory named /Content/ as well?
/Content is a controller, which is basically just a collection of actions. ASP.NET MVC needs to know WHICH action you want to run, so by leaving out the action asp.net mvc doesn't know what action to return and gives a 404.
You can tell it a default either by adding a route:
eg:
routes.MapRoute("ContentDefault", "Content", new {controller = "Content", action = "Index"});
The attributes are defined as follows:
'ContentDefault`: Name of the Route (must be unique in your routing table)
Content: The URL segment (try changing this to 'Content/Much/Longer/URL' and then go to http://localhost/Content/Much/Longer/URL to see how this works)
new {controller=.., action=...}: which controller/action combo to run for this route.
You could also override HandleUnknownAction in your controller:
protected override void HandleUnknownAction(string actionName)
{
return RedirectToAction("index");
}
Oh and incidentally, an extra piece of advice about routing.... if you add something to the route in braces { } these will be passed to the action as an attribute.
e.g. /Content/Much/Longer/Url/{page}
so the URL http://localhost/Content/Much/Longer/Url/999
will pass the 999 into your action, as the page attribute
public ActionResult Index(int Page) { }
I love MVC - never going back to WebForms - this is how web development should be!

Resources