I am writing a fairly simple MVC3 application that allows a user to retrieve and modify some configuration data held by a WCF service. The configuration data will not change very often but needs to be maintainable by the user.
Once the user is happy with the configuration, they will launch some processing from the UI or by the scheduled execution of a VB script.
I'm fairly new to WCF and even newer to MVC3 but I'd like to make all the comms to and from the service RESTful. Is this a good thing to do?
I'd been planning to perform the service communications from the MVC controller. This would make a HTTP Get request to retrieve the current configuration and a HTTP Post to apply the modified configuration. I'd also use a Get request to launch the processing.
Could anyone provide an example (or point me in the direction) of how I should be doing this?
Please follow the below links for some sample code to build a RESTful WCF Service and the how the client would access the service.
Link to create a RESTful service: here
Link to create a .NET client that consumes the RESTful service : here
Hope the information helps you out.
If you are the owner of web service, you can directly reference implementation of service in your mvc project and use it without web reference. You can write some like this:
// example of ws
public class Service1 : IService1
{
public string GetData( int value )
{
return string.Format( "You entered: {0}", value );
}
public CompositeType GetDataUsingDataContract( CompositeType composite )
{
if( composite == null )
{
throw new ArgumentNullException( "composite" );
}
if( composite.BoolValue )
{
composite.StringValue += "Suffix";
}
return composite;
}
}
// example of mvc action
public class HomeController : Controller
{
public ActionResult Index()
{
IService1 service = new Service1();
service.GetDataUsingDataContract(....)
ViewBag.Message = "Welcome to ASP.NET MVC!";
return View();
}
}
The simplest answer I've found was here:, using the channel factory.
I still don't know if it's the best way but it left my code looking clean enough. Below is a sample from my controller.
public ActionResult Index()
{
SettingsModel config = null;
// Set up a channel factory to use the webHTTPBinding
using (WebChannelFactory<IChangeService> serviceChannel =
new WebChannelFactory<IChangeService>(new Uri(baseServiceUrl )))
{
IChangeService channel = serviceChannel.CreateChannel();
config = channel.GetSysConfig();
}
ViewBag.Message = "Service Configuration";
return View(config);
}
Related
Can you help me point out how should I start on this:
I'm new to API , and I'm currently working on ASP.NET Core 3.1 MVC paired with Microsoft SQL Server. I have requirement that I should use API (ServiceStack) for a certain method.
My question are :
how or where do I start from my existing project solution?
If I use API should it be calling on SQL also? (I supposed the data will stay on db)
with regards to first question : they gave me a link where I can see this.
Where should I start , I'm just so confused.
I've looked up on youtube but there's no similar case to mine, they all use in-memory.
Suggestions and advice are welcome !
Go through ServiceStack's Getting Started Section starting with Create your first Web Service.
Configure OrmLite in your AppHost
To configure OrmLite, start with the OrmLite Installation tells you which package to download whilst the OrmLite Getting Started docs lists all the available SQL Server Dialects which you'd use to configure the OrmLiteConnectionFactory in your IOC.
E.g. for SQL Server 2012:
public class AppHost : AppHostBase
{
public AppHost() : base("MyApp", typeof(MyServices).Assembly) { }
// Configure your ServiceStack AppHost and App dependencies
public override void Configure(Container container)
{
container.AddSingleton<IDbConnectionFactory>(
new OrmLiteConnectionFactory(connectionString,
SqlServer2012Dialect.Provider));
}
}
Using OrmLite in Services
Then inside your ServiceStack Services you can access your ADO .NET DB connection via base.Db which you can use with OrmLite's extension methods, e.g:
public class MyServices : Service
{
public object Any(GetAllItems request) => new GetAllItemsResponse {
Results = Db.Select<Item>()
};
}
Checkout the OrmLite APIs docs for different APIs to Select, Insert, Update & Delete Data.
Creating effortless RDBMS APIs using AutoQuery
As you're new I'd highly recommend using AutoQuery RDBMS since it lets you create RDBMS APIs with just Request DTOs.
You can enable it by adding the AutoQueryFeature plugin in the ServiceStack.Server" NuGet package:
public override void Configure(Container container)
{
Plugins.Add(new AutoQueryFeature { MaxLimit = 100 });
}
Then you can create an AutoQuery API for your Item table with just:
[Route("/items")]
public class QueryItems : QueryDb<Item> {}
Which will now let you query each Item column using any of AutoQuery's implicit conventions, e.g by exact match:
/items?Id=1
Or by any of the query properties:
/items?NameStartsWith=foo
Creating Typed Request DTO
Once you know which Query APIs your client Apps needs I'd recommend formalizing them by adding them as strong typed properties in your Request DTO, e.g:
[Route("/items")]
public class QueryItems : QueryDb<Item>
{
public int? Id { get; set; }
public string NameStartsWith { get; set; }
}
Calling from Service Clients
Which will enable an end-to-end Typed API using any of ServiceStack's Service Clients, e.g:
var client = new JsonServiceClient(BaseUrl);
var response = client.Get(new QueryItems { NameStartsWith = "foo" });
response.PrintDump(); // quickly view results in Console
There's also AutoQuery CRUD APIs that will let you create APIs that modify your RDBMS tables using just Request DTOs.
In asp.net core web I create a controller and I can use:
return Json(new {status=true});
but in asp.net core web API I can't do it.
In a controller:
[HttpGet("{id}")]
public JsonResult Get(int id)
{
}
I can not return Json()
How to use it?
Asp.Net Core Web API does provide support for wide varieties of response types, with Json being one among them. You can do that like shown below. Make sure you have all your required dependencies. You can learn about the dependencies from the documentation link I attached in this answer.
[HttpGet]
public IActionResult Get()
{
return Json(model);
}
You can also specify strict response formats using the [Produces] Filter on your controller.
Configuring Custom Formatters
You can also configure your own custom formatters in Asp.Net Web API project by calling the .AddFormatterMappings() from ConfigureServices method inside of your Startup.cs. This allows for a greater control on your content negotiation part and lets you achieve strict restrictions.
Please go through this documentation to understand further.
Using Responses with Status Codes
However, when using Web API, I suggest you use the helper methods that are built in so that your response becomes more expressive as it contains both the response content along with the status code. An example of how to do that is below
[HttpGet]
public ActionResult Get()
{
return Ok(_authors.List());
}
For a full list of helper methods available, you can take a look at the Controller.cs and ControllerBase.cs classes.
Asp.net core web api inherit from controllerBase, which doesn't contain a Json(Object) method. You should initialize a new JsonResult yourself in the action.
[HttpGet("{id}")]
public JsonResult Get(int id)
{
return new JsonResult(new { status = true });
}
In my solution I have projects for my API, my Web App and also have another project which includes services, that are getting some information from a database and formatting them, these are currently only used by this API, but these could be used by other API projects in the future.
My API have a couple controllers that are returning JSON data from the result returned by the services.
In some cases the services needs to call the API to process some information before calling the request to the database. Since I have dev/staging/prod environment with their own URL I don't want to hardcode the URLs in the services I want to use DI to get these dynamicaly depending on the context.
In the Startup.cs of my API I have added services.AddHttpContextAccessor(); in the ConfigureServices(IServiceCollection services) section to gain access to the current http context :
public void ConfigureServices(IServiceCollection services)
{
...
services.AddHttpContextAccessor();
...
}
With that I know I can now access the information directly into my controller which I tried and it worked :
public class DataController : ControllerBase
{
...
private readonly string _baseUrl;
public FeaturesController(...
,IHttpContextAccessor httpContextAccessor)
{
...
_baseUrl = UrlHelpers.ShowBaseURL(httpContextAccessor) ?? throw new ArgumentNullException(nameof(_baseUrl));
}
}
public static class UrlHelpers
{
public static string ShowBaseURL(IHttpContextAccessor httpcontextaccessor)
{
var request = httpcontextaccessor.HttpContext.Request;
var absoluteUri = string.Concat(
request.Scheme,
"://",
request.Host.ToUriComponent(),
request.PathBase.ToUriComponent());
return absoluteUri;
}
}
I could do just about the same thing in the services but to me they should not act directly on the httpcontext, since this is not the job they are meant to do. I am sure I could do better by adding a class injected of some sort that would have then make the specific value available to my services.
I know I could also pass the _baseUrl directly as an argument when calling the services from my controller but since I am trying to better understand DI and use it I would rather find another way if it is viable.
I can't give credit but I went with Steven solution which make the most sens
I have a set of AspNet WebApi-based web services and an IdentityServer3-based authentication service. All of the web services support a simple service info endpoint that we use for monitoring and diagnosis. It reports the service version and the server name. The only service that currently does not support the service info endpoint is the IdentityServer3-based authentication service.
Is there a way to add a simple endpoint to an IdentityServer3-based service? In GitHub issue 812 Brock Allen says "We have a way to add custom controllers, but it's undocumented, current unsupported, and not really done." I'd rather not take that indocumented, unsupported route.
Is there a way to modify/extend the discovery endpoint to include additional information?
Here's how I ended up coding this up. At a high level, basically I added a Controllers folder, created a AuthenticationServiceInfoController class with a single GET action method and then registered that controller during Startup. As noted in comment above, my solution had some extra complexity because my AuthenticationServiceInfoController inherited from a base ServiceInfoController defined elsewhere, but I've tried to eliminate that from this sample. So, the controller code looks like this:
[RoutePrefix("api/v1/serviceinfo")]
public class AuthencticationServiceInfoController : IServiceInfoController
{
[Route("")]
[Route("~/api/serviceinfo")]
public IHttpActionResult Get()
{
try
{
ServiceInformation serviceInfo = new ServiceInformation();
serviceInfo.ServiceVersion = Global.serviceVersion;
return Ok(serviceInfo);
}
catch (Exception ex)
{
return InternalServerError(ex);
}
}
}
It implements a simple interface:
public interface IServiceInfoController
{
IHttpActionResult Get();
}
And in my Startup.Configuration method where I configure Identity Server, I've got:
var idSrvFactory = new IdentityServerServiceFactory();
idSrvFactory.Register(new Registration<IServiceInfoController, Controllers.AuthencticationServiceInfoController>());
I think that's all that it took. It's in place and working in my Identity Server 3-based service.
I want to know what is the opinion of you fellow Developers regarding WCF WebApi services.
In an N-tier application we can have multiple layers of services. We can have services consuming data from external services. In that scenario its worth to create Async Rest Services using WCF 4.0.
public interface IService
{
[OperationContractAttribute(AsyncPattern = true)]
IAsyncResult BeginGetStock(string code, AsyncCallback callback, object asyncState);
//Note: There is no OperationContractAttribute for the end method.
string EndGetStock(IAsyncResult result);
}
But with the release of WCF WebApi this approach is still required? to create async services?
How to host them in IIS/WAS/Self Hosting
looking forward for suggestion and comments.
Well What i feel,In order to create asynchronous operations in the latest WCF WebAPIs (preview 6) I can still use same pattern (Begin/End), but I can also use the Task programming model to create asynchronous operations, which is a lot simpler.
One example of an asynchronous operation written using the task model is shown below.
[WebGet]
public Task<Aggregate> Aggregation()
{
// Create an HttpClient (we could also reuse an existing one)
HttpClient client = new HttpClient();
// Submit GET requests for contacts and orders
Task<List<Contact>> contactsTask = client.GetAsync(backendAddress + "/contacts").ContinueWith<Task<List<Contact>>>((responseTask) =>
{
return responseTask.Result.Content.ReadAsAsync<List<Contact>>();
}).Unwrap();
Task<List<Order>> ordersTask = client.GetAsync(backendAddress + "/orders").ContinueWith<Task<List<Order>>>((responseTask) =>
{
return responseTask.Result.Content.ReadAsAsync<List<Order>>();
}).Unwrap();
// Wait for both requests to complete
return Task.Factory.ContinueWhenAll(new Task[] { contactsTask, ordersTask },
(completedTasks) =>
{
client.Dispose();
Aggregate aggregate = new Aggregate()
{
Contacts = contactsTask.Result,
Orders = ordersTask.Result
};
return aggregate;
});
}
[WebGet(UriTemplate = "contacts")]
public Task<HttpResponseMessage> Contacts()
{
// Create an HttpClient (we could also reuse an existing one)
HttpClient client = new HttpClient();
// Submit GET requests for contacts and return task directly
return client.GetAsync(backendAddress + "/contacts");
}
WCF Web API comes with an completely async HttpClient implementation and you can host in IIS and also completely sefhost.
For a async REST "service" scenario please read "Slow REST"